axios某一接口失败后不调用_axios 源码系列之如何取消请求
我們在前后端交互的過程中,通常是通過請求接口來實現(xiàn)的,而一個頁面中的交互又非常復(fù)雜,例如需要多次頻繁請求同一個接口,或者在接口還沒返回時就要切換路由等。這些都需要對接口請求的時機(jī)或者請求接口之后進(jìn)行處理,避免一些無用的請求或者接口返回順序的差異。
前兩種方式,是在發(fā)起請求前進(jìn)行控制,即控制發(fā)起請求的時機(jī),而當(dāng)請求發(fā)出之后則不再控制;而最終一種方式則是取消中斷還在路上的請求,然后再發(fā)起一個新的請求,不用管發(fā)起的時機(jī)。這幾種方式也要看業(yè)務(wù)的需要,選擇最適合的即可。
我們在之前的如何實現(xiàn) axios 的自定義適配器 adapter文章里,略過了 axios 是如何主動取消當(dāng)前請求的。今天我們就將一下在 axios 中如何取消之前發(fā)起的請求,源碼中又是怎樣實現(xiàn)的。
1. 主動取消之前發(fā)起的請求
我們先來看下 axios 中取消請求的用法:
const CancelToken = axios.CancelToken;// 返回兩個字段,{ token, cancel } // token用于表示某個請求,是一個Promise類型 // cancel是一個方法,當(dāng)被調(diào)用時,則取消token注入的那個請求 const source = CancelToken.source();axios.get('/user/12345', {cancelToken: source.token, // 將token注入到請求中}).catch(function (thrown) {// 判斷是否是因主動取消導(dǎo)致的if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// handle errorconsole.error(thrown);}});axios.post('/user/12345',{name: 'new name',},{cancelToken: source.token,} );// 主動取消請求 // cancel方法會把注入的同一個token的請求方法一并取消掉 // 上面的get和post請求都會被取消掉 // cancel the request (the message parameter is optional) source.cancel('Operation canceled by the user.');從 demo 上來看,用法很簡單,token 和 cancel 的關(guān)系對應(yīng)上即可。
官方例子中還有一種取消請求的方式,這個我們放在后面講,更容易理解一些。
2. 源碼解析
取消請求的方法在 https://github.com/axios/axios/tree/master/lib/cancel 的目錄中,3 個文件:
- Cancel: Cancel 類,message 和__CANCEL__屬性,用于標(biāo)識取消的某個請求;
- isCancel: 判斷當(dāng)前參數(shù)是否是 Cancel 的實例;
- CancelToken: 主流程,創(chuàng)建 Cancel 實例和取消的方法;
我們主要來看下 CancelToken 中的整個流程。
2.1 source 方法
source 作為取消請求的入口,我們就先來看下 source 方法。
// 創(chuàng)建token和cancel方法 CancelToken.source = function source() {var cancel;// token為 CancelToken 的實例,包含 promise 和 reason 兩個屬性// 同時把 executor 中的參數(shù)給到 cancel// 即CancelToken有一個回調(diào)函數(shù),而這個回調(diào)函數(shù)的參數(shù)也是一個函數(shù)// CancelToken怎么執(zhí)行,我們接著看!var token = new CancelToken(function executor(c) {cancel = c;});return {token: token,cancel: cancel,}; };2.2 CancelToken
CancelToken 用來取消請求,但我理解起來,思路非常的繞,我們一點點來剖析:
function CancelToken(executor) {if (typeof executor !== 'function') {throw new TypeError('executor must be a function.');}// 創(chuàng)建一個Promise的實例,// 當(dāng)resolvePromise執(zhí)行時,this.promise變?yōu)閒ulfilled狀態(tài)var resolvePromise;this.promise = new Promise(function promiseExecutor(resolve) {resolvePromise = resolve;});// new一個實例時,會立即執(zhí)行CancelToken的回調(diào)函數(shù)executor方法// executor的參數(shù)也是一個函數(shù),即上面的cancel就是當(dāng)前的cancel函數(shù)體// 當(dāng)executor的回調(diào)函數(shù)cancel執(zhí)行時,會給當(dāng)前CancelToken創(chuàng)建一個reason屬性,這個屬性是Cancel的實例// 并執(zhí)行resolvePromise方法,將reason實例穿進(jìn)去;執(zhí)行后this.promise變?yōu)閒ulfilled狀態(tài)var token = this;executor(function cancel(message) {if (token.reason) {// Cancellation has already been requestedreturn;}token.reason = new Cancel(message);resolvePromise(token.reason);}); }也就是說會先創(chuàng)建一個 CancelToken 的實例 token,同時,將 CancelToken 中回調(diào)函數(shù)的參數(shù)給到了 cancel。當(dāng) cancel 執(zhí)行時,則 token 中的 promise 屬性則會從 pending 狀態(tài)變?yōu)?fulfilled 狀態(tài),那么 promise 上掛載的then()方法也就可以繼續(xù)執(zhí)行了。
2.3 adapter
在調(diào)用 cancel 方法后,請求中是怎么操作的呢?我們看下adapter/xhr.js中的代碼:
if (config.cancelToken) {// config.cancelToken就是上面創(chuàng)建的token// 當(dāng)token.promise變?yōu)閒ulfilled狀態(tài)后,就可以執(zhí)行后續(xù)的鏈?zhǔn)讲僮?/ Handle cancellationconfig.cancelToken.promise.then(function onCanceled(cancel) {if (!request) {return;}// 取消當(dāng)前的請求request.abort();// 將Cancel的實例cancel給到rejectreject(cancel);// Clean up requestrequest = null;}); }當(dāng)我們使用 axios 的 catch 捕獲內(nèi)部拋出的異常時,就可以通過isCancel判斷是否是因主動取消請求導(dǎo)致的異常:
axios.get('/user/12345', {cancelToken: source.token, // 將token注入到請求中}).catch(function (thrown) {// 判斷是否是因主動取消導(dǎo)致的if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// handle errorconsole.error(thrown);}});現(xiàn)在再來看下 cancel 執(zhí)行的整個流程,就會清晰流暢很多。
3. 取消請求的另一種方式
我們在第 1 節(jié)還留著一個問題,axios 取消請求還有另一種方式,即直接使用 CancelToken 類。
其實我們發(fā)現(xiàn),source()方法,只是給我們額外又封裝了一下,簡單的返回了 token 和 cancel,但本質(zhì)還是 CancelToken 中的東西。
4. 總結(jié)
在取消請求的過程中,token 要和 cancel 方法保持對應(yīng)關(guān)系,即都在一個對象里;若其他的請求也要取消時,可以額外再生成一組 token 和 cancel。同時,這里還用到了 Promise 的一個機(jī)制,只有在當(dāng)前 Promise 變更為 fulfilled 狀態(tài)后,才能執(zhí)行后面的 then 等操作。
更多文章歡迎查看我的博客:
蚊子的前端博客?www.xiabingbao.com總結(jié)
以上是生活随笔為你收集整理的axios某一接口失败后不调用_axios 源码系列之如何取消请求的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Maven and Nexus2
- 下一篇: 多款局域网工具