【實戰(zhàn)】Axios取消請求 - CancelToken

# 鋪墊

? Axios 是一個基于 Promise 的 HTTP 庫,它的瀏覽器支持性良好,是Vue主推請求異步的方法;它支持多種請求的簡寫和請求參數(shù)的配置逞盆,也支持使用自定義配置新建一個axios實例,舉例如下

const request = axios.create({
  baseURL: 'https://domain-name.com/api/'
  timeout: 8000
})

? 其中松申,create()方法中是自定義的初始化配置參數(shù)云芦。初始化數(shù)據(jù)除此之外,通常還會設(shè)置攔截器贸桶,實現(xiàn)header參數(shù)添加舅逸,錯誤打印及HTTP碼的統(tǒng)一處理等,如下

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    if (store.getters.token) {
      config.headers.common['X-Token'] = getToken()
      config.headers.common['X-Requested-With'] = 'XMLHttpRequest'
      config.headers.common['Access-Control-Allow-Origin'] = '*'
      config.params = {
        _t: Date.parse(new Date()) / 1000,
        ...config.params
      }
    return config;
  }, function (error) {
    console.log('request error:', error)
    return Promise.reject(error);
  });

// 添加響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
    if (res.code !== 0) {
      console.log(`請求錯誤: ${res.request.responseURL} \nCode: ${res.data.code}`);
    }
    return response;
  }, function (error) { // request timeout is an error
    let msg = 'UnknownError'
    const res = error.response
    if (res) {
      msg = errorMessage.find((t) => t.code === res.status).msg || msg
      if (res.status === 401 || res.status === 403) {
        window.location.href = res.data.redirect_url
      } else {
        Message.error(msg)
      }
    } else {
      Message.error(error.message)
    }
    return Promise.reject(error);
  });
// HTTP CODE及錯誤提示
const errorMessage = [
  { code: 400, msg: '請求錯誤' },
  { code: 401, msg: '未授權(quán)皇筛,請登錄' },
  { code: 403, msg: '拒絕訪問' },
  { code: 404, msg: '請求地址出錯' },
  { code: 408, msg: '請求超時' },
  { code: 500, msg: '服務(wù)器內(nèi)部錯誤' },
  { code: 501, msg: '服務(wù)未實現(xiàn)' },
  { code: 502, msg: '網(wǎng)關(guān)錯誤' },
  { code: 503, msg: '服務(wù)不可用' },
  { code: 504, msg: '網(wǎng)關(guān)超時' },
  { code: 505, msg: 'HTTP版本不受支持' }
]

? 一般我們將它封裝為request.js文件并暴露出接口以便外部使用琉历。在外部調(diào)用的過程中,如遇到不符合要求或需要新增的config參數(shù)是允許覆蓋和新增的水醋,編寫如下

import request from '@/request'

export function queryUserInfo(data) {
  return request({
    url: '/users/userInfo',
    method: 'get',
    params: data
  })
}

? 這里旗笔,request方法中的配置參數(shù)會按一定的規(guī)則merge到最終的Axios請求中。
?

# 取消重復(fù)的請求

? 先來回顧一下官網(wǎng)講解的內(nèi)容

Axios使用cancel token取消請求拄踪,它基于cancelable promises proposal實現(xiàn)蝇恶,目前該API還處在第一階段

? 官網(wǎng)介紹了取消請求的兩種辦法:

1. 可以利用CancelToken工廠函數(shù)創(chuàng)建cancel token
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
// get 方法使用案例
axios.get('user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message)
  } else {
    // TODO: handle error
  }
})
// post 使用案例
axios.post('/user/12345', {
  name: 'name what'
}, {
  cancelToken: source.token
})

// 執(zhí)行取消請求操作
source.cancel(‘請求已取消’)
2. 傳遞executor函數(shù)到CancelToken的夠造函數(shù)來創(chuàng)建cancel token
const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    cancel = c
  })
})

// 執(zhí)行取消請求操作
cancel()

? 并且官網(wǎng)特意強調(diào)了,不同請求可以定義同一個取消請求的方法名宫蛆,來批量取消多個請求艘包。

# 案例

? 結(jié)合【鋪墊】內(nèi)容的猛,筆者使用方法2來舉例實現(xiàn)取消請求耀盗,還是拿上方的請求為例,做如下修改

import request from '@/utils/request'
import axios from 'axios'

export function queryUserInfo(data, _this) {
  const CancelToken= axios.CancelToken
  return request({
    url: '/users/userInfo',
    method: 'get',
    params: data,
    cancelToken: new CancelToken(function executor(c) {
      _this.cancelAjax = c
    })
  })
}

? 以上我們利用executor生成了取消函數(shù)卦尊,并賦值給外部真實請求傳入的環(huán)境中叛拷,形參_this的實參為Vue的this變量。

// 選擇人員列表查詢
getUserInfo() {
  if (typeof this.cancelAjax === 'function') {
    this.cancelAjax()
  }
  this.allUsers.loading = true
  queryUserInfo({ userId: '20192430139' }, this).then(res => {
    if (res.code === 1) {
      this.userInfo.data = res.data
      this.allUsers.loading = false
    } else {
      this.$message.error(res.msg || 'get userInfo error')
    }
  })
}

? 思路就是岂却,當請求發(fā)起時cancelToken會派發(fā)函數(shù)給data中的cancelAjax忿薇,可以利用數(shù)據(jù)類型偵查是否請求正在發(fā)生裙椭。cancelAjax在頁面初始化時定義為null即可

<template>

</template>
<script>
export default {
  data() {
    return {
      cancelAjax: null
    }
  }
}
</script>

? 至此,已實現(xiàn)了基本邏輯署浩,在頁面連續(xù)出發(fā)請求時揉燃,可以看到請求的取消表現(xiàn)


取消舉例

?


# 通過攔截器實現(xiàn)統(tǒng)一處理

? 修改你的請求二次封裝文件,大致如下

// request.js
import axios from 'axios'

const cancelToken = {} // 數(shù)組用于儲存每個請求的取消函數(shù)和請求標識
const CancelToken = axios.CancelToken


// 取消被多次發(fā)起的請求筋栋,保留最后一個
const cancelAjax = (type, config) => {
    const key = getUrlKey(config)
    if (type === 'check') {
        if (!cancelToken[key]) {
            config.cancelToken = new CancelToken((c) => {
                cancelToken[key] = c
            })
        } else {
            cancelToken[key]()
        }
    } else if (type === 'remove') {
        delete cancelToken[key]
    }
}

// 允許多次重復(fù)調(diào)用的API白名單
const whiteList = []

// request interceptor
service.interceptors.request.use((config) => {
    if (!whiteList.includes(config.url)) {
        cancelAjax('check', config)
    }
    return config
}, err => {
    console.log('request intercepter err:' + err) // 打印錯誤
    return Promise.reject(err)
})

// response interceptor
service.interceptors.response.use(
    async response => {
        cancelAjax('remove', response.config)
        const res = response.data
        ...
    },
    err => {
        console.log('response intercepter err: ' + err) // 打印錯誤
        ...
        return Promise.reject(err)
    }
)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炊汤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子弊攘,更是在濱河造成了極大的恐慌抢腐,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件襟交,死亡現(xiàn)場離奇詭異迈倍,居然都是意外死亡,警方通過查閱死者的電腦和手機捣域,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門啼染,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人焕梅,你說我怎么就攤上這事提完。” “怎么了丘侠?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵徒欣,是天一觀的道長。 經(jīng)常有香客問我蜗字,道長打肝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任挪捕,我火速辦了婚禮粗梭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘级零。我一直安慰自己断医,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布奏纪。 她就那樣靜靜地躺著鉴嗤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪序调。 梳的紋絲不亂的頭發(fā)上醉锅,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音发绢,去河邊找鬼硬耍。 笑死垄琐,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的经柴。 我是一名探鬼主播狸窘,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坯认!你這毒婦竟也來了朦前?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鹃操,失蹤者是張志新(化名)和其女友劉穎韭寸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荆隘,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡恩伺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了椰拒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晶渠。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖燃观,靈堂內(nèi)的尸體忽然破棺而出褒脯,到底是詐尸還是另有隱情,我是刑警寧澤缆毁,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布番川,位于F島的核電站,受9級特大地震影響脊框,放射性物質(zhì)發(fā)生泄漏颁督。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一浇雹、第九天 我趴在偏房一處隱蔽的房頂上張望沉御。 院中可真熱鬧,春花似錦昭灵、人聲如沸吠裆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽试疙。三九已至,卻和暖如春窜护,著一層夾襖步出監(jiān)牢的瞬間效斑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工柱徙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缓屠,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓护侮,卻偏偏與公主長得像敌完,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子羊初,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容