前景提要:
ts 簡易封裝 axios,統(tǒng)一 API
實(shí)現(xiàn)在 config 中配置開關(guān)攔截器
請求重試的核心是可以重放請求,具體實(shí)現(xiàn)就是在 axios 中,拿到當(dāng)前請求的 config 對象,再用 axios 實(shí)例,就能重放請求。
在無感刷新 token 中,當(dāng) access token 過期,使用 refresh token 刷新后,就需要再次對業(yè)務(wù)接口重放請求。
上面是一種請求重試的場景,一般情況下也不需要重試,所以我們這里講的請求重試,指的都是請求網(wǎng)絡(luò)錯誤的情況下需要重試。
比如斷網(wǎng)了,然后重試。而不是因?yàn)榻涌诜祷?code 如 401 就重試。因?yàn)榻涌诜祷?401,從網(wǎng)絡(luò)層面上講,這是沒有失敗的,http 狀態(tài)碼是 200,返回 401 只是業(yè)務(wù)失敗。
比起斷網(wǎng),更常見的網(wǎng)絡(luò)錯誤下需要重試的是請求超時。
通過錯誤攔截器實(shí)現(xiàn)請求重試。整個請求過程是一個遞歸。
第一次請求失敗,觸發(fā)全局錯誤攔截,然后一路拋出錯誤,觸發(fā)到重試的錯誤攔截器。判斷還有重試次數(shù)后,拿到同一個實(shí)例重放請求。注意此時第一次請求并未結(jié)束,this.instance.request 方法依舊在等待結(jié)果。
如果請求依舊失敗,則觸發(fā)第二次請求的全局錯誤攔截,最后再次觸發(fā)重試。如果第二次請求重試成功了,此時就拿到了請求結(jié)果。并且為了讓結(jié)果最終被第一次請求捕獲,需要在錯誤攔截器中拋出 fulfilled 狀態(tài)的 promise 攜帶結(jié)果。
當(dāng)請求次數(shù)用完,則錯誤攔截器繼續(xù)拋出錯誤對象,觸發(fā)第一次請求的 request 方法的 catch 代碼塊。宣告整個請求失敗。
注意:文章來源:http://www.zghlxwxcb.cn/news/detail-743010.html
- 一定要以同一個 axios 實(shí)例重新發(fā)起請求,因?yàn)楸举|(zhì)是遞歸,換個一個實(shí)例就拿不到重試成功后的請求結(jié)果了。
- 并且還需要在這個重試的錯誤攔截器中返回一個 fulfilled 狀態(tài)的 promise,讓第一次請求的實(shí)例方法捕獲。
return Promise.resolve(res); 或 Promise.rejected(234); 都表示返回一個確定了狀態(tài)的 promise,然后這個 promise 中攜帶了數(shù)據(jù)(就是參數(shù))。文章來源地址http://www.zghlxwxcb.cn/news/detail-743010.html
import httpRequest from "..";
import { MyAxiosError, MyAxiosRequestConfig } from "./request";
const MAX_RETRY_COUNT = 3;
const DELAY_TIME = 2000;
let currentCount = 1;
/**
* 請求重試
* @param err 錯誤對象
* @returns 重試機(jī)會用完拋出錯誤,重試成功則返回請求結(jié)果
*/
export async function retryRequest(err: MyAxiosError) {
if (err.config.retry === false) throw err;
if (err.message === "canceled") throw err; // 過濾手動取消請求的情況
const config = err.config as MyAxiosRequestConfig;
if (MAX_RETRY_COUNT >= currentCount && config) {
console.log(`重試${currentCount}次...`);
currentCount++;
await sleep(DELAY_TIME);
const res = await httpRequest.getInstance().request({ ...config });
return Promise.resolve(res);
}
console.log("重試次數(shù)已用完...");
currentCount = 0;
throw err;
}
/**
* 延遲后續(xù)代碼執(zhí)行的工具函數(shù),以同步代碼阻塞的方式實(shí)現(xiàn)延遲:await sleep()
* @param delayTime 延遲時間
* @returns Promise
*/
export function sleep(delayTime: number = 1000) {
return new Promise(resolve => setTimeout(resolve, delayTime));
}
到了這里,關(guān)于axios 實(shí)現(xiàn)請求重試的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!