日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

面试官:请手写一个带取消功能的延迟函数,axios 取消功能的原理是什么

發(fā)布時間:2023/12/9 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 面试官:请手写一个带取消功能的延迟函数,axios 取消功能的原理是什么 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

大家好,我是若川。最近組織了源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學(xué)習(xí)200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學(xué)習(xí)源碼整體架構(gòu)系列》?包含20余篇源碼文章。

本文倉庫 https://github.com/lxchuan12/delay-analysis.git,求個star^_^[1]

源碼共讀活動 每周一期,已進行到17期。于是搜尋各種值得我們學(xué)習(xí),且代碼行數(shù)不多的源碼。delay 主文件僅70多行[2],非常值得我們學(xué)習(xí)。

閱讀本文,你將學(xué)到:

1.?學(xué)會如何實現(xiàn)一個比較完善的?delay?函數(shù) 2.?學(xué)會使用?AbortController?實現(xiàn)取消功能 3.?學(xué)會面試常考?axios?取消功能實現(xiàn) 4.?等等

2. 環(huán)境準(zhǔn)備

#?推薦克隆我的項目,保證與文章同步 git?clone?https://github.com/lxchuan12/delay-analysis.git #?npm?i?-g?yarn cd?delay-analysis/delay?&&?yarn?i #?VSCode?直接打開當(dāng)前項目 #?code?. #?我寫的例子都在?examples?這個文件夾中,可以啟動服務(wù)本地查看調(diào)試 #?在?delay-analysis?目錄下 npx?http-server?examples #?打開?http://localhost:8080#?或者克隆官方項目 git?clone?https://github.com/sindresorhus/delay.git #?npm?i?-g?yarn cd?delay?&&?yarn?i #?VSCode?直接打開當(dāng)前項目 #?code?.

3. delay

我們從零開始來實現(xiàn)一個比較完善的 delay 函數(shù)[3]

3.1 第一版 簡版延遲

要完成這樣一個延遲函數(shù)。

3.1.1 使用

(async()?=>?{await?delay1(1000);console.log('輸出這句'); })();

3.1.2 實現(xiàn)

用 Promise 和 setTimeout 結(jié)合實現(xiàn),我們都很容易實現(xiàn)以下代碼。

const?delay1?=?(ms)?=>?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{resolve();},?ms);}); }

我們要傳遞結(jié)果。

3.2 第二版 傳遞 value 參數(shù)作為結(jié)果

3.2.1 使用

(async()?=>?{const?result?=?await?delay2(1000,?{?value:?'我是若川'?});console.log('輸出結(jié)果',?result); })();

我們也很容易實現(xiàn)如下代碼。傳遞 value 最后作為結(jié)果返回。

3.2.2 實現(xiàn)

因此我們實現(xiàn)也很容易實現(xiàn)如下第二版。

const?delay2?=?(ms,?{?value?}?=?{})?=>?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{resolve(value);},?ms);}); }

這樣寫,Promise 永遠是成功。我們也需要失敗。這時我們定義個參數(shù) willResolve 來定義。

3.3 第三版 willResolve 參數(shù)決定成功還是失敗。

3.3.1 使用

(async()?=>?{try{const?result?=?await?delay3(1000,?{?value:?'我是若川',?willResolve:?false?});console.log('永遠不會輸出這句');}catch(err){console.log('輸出結(jié)果',?err);} })();

3.3.2 實現(xiàn)

加個 willResolve 參數(shù)決定成功還是失敗。于是我們有了如下實現(xiàn)。

const?delay3?=?(ms,?{value,?willResolve}?=?{})?=>?{return?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{if(willResolve){resolve(value);}else{reject(value);}},?ms);}); }

3.4 第四版 一定時間范圍內(nèi)隨機獲得結(jié)果

延時器的毫秒數(shù)是寫死的。我們希望能夠在一定時間范圍內(nèi)隨機獲取到結(jié)果。

3.4.1 使用

(async()?=>?{try{const?result?=?await?delay4.reject(1000,?{?value:?'我是若川',?willResolve:?false?});console.log('永遠不會輸出這句');}catch(err){console.log('輸出結(jié)果',?err);}const?result2?=?await?delay4.range(10,?20000,?{?value:?'我是若川,range'?});console.log('輸出結(jié)果',?result2); })();

3.4.2 實現(xiàn)

我們把成功 delay 和失敗 reject 封裝成一個函數(shù),隨機 range 單獨封裝成一個函數(shù)。

const?randomInteger?=?(minimum,?maximum)?=>?Math.floor((Math.random()?*?(maximum?-?minimum?+?1))?+?minimum);const?createDelay?=?({willResolve})?=>?(ms,?{value}?=?{})?=>?{return?new?Promise((relove,?reject)?=>?{setTimeout(()?=>?{if(willResolve){relove(value);}else{reject(value);}},?ms);}); }const?createWithTimers?=?()?=>?{const?delay?=?createDelay({willResolve:?true});delay.reject?=?createDelay({willResolve:?false});delay.range?=?(minimum,?maximum,?options)?=>?delay(randomInteger(minimum,?maximum),?options);return?delay; } const?delay4?=?createWithTimers();

實現(xiàn)到這里,相對比較完善了。但我們可能有需要提前結(jié)束。

3.5 第五版 提前清除

3.5.1 使用

(async?()?=>?{const?delayedPromise?=?delay5(1000,?{value:?'我是若川'});setTimeout(()?=>?{delayedPromise.clear();},?300);//?300?milliseconds?laterconsole.log(await?delayedPromise);//=>?'我是若川' })();

3.5.2 實現(xiàn)

聲明 settle變量,封裝 settle 函數(shù),在調(diào)用 delayPromise.clear 時清除定時器。于是我們可以得到如下第五版的代碼。

const?randomInteger?=?(minimum,?maximum)?=>?Math.floor((Math.random()?*?(maximum?-?minimum?+?1))?+?minimum);const?createDelay?=?({willResolve})?=>?(ms,?{value}?=?{})?=>?{let?timeoutId;let?settle;const?delayPromise?=?new?Promise((resolve,?reject)?=>?{settle?=?()?=>?{if(willResolve){resolve(value);}else{reject(value);}}timeoutId?=?setTimeout(settle,?ms);});delayPromise.clear?=?()?=>?{clearTimeout(timeoutId);timeoutId?=?null;settle();};return?delayPromise; }const?createWithTimers?=?()?=>?{const?delay?=?createDelay({willResolve:?true});delay.reject?=?createDelay({willResolve:?false});delay.range?=?(minimum,?maximum,?options)?=>?delay(randomInteger(minimum,?maximum),?options);return?delay; } const?delay5?=?createWithTimers();

3.6 第六版 取消功能

我們查閱資料可以知道有 AbortController 可以實現(xiàn)取消功能。

caniuse AbortController[4]

npm abort-controller[5]

mdn AbortController[6]

fetch-abort[7]

fetch#aborting-requests[8]

yet-another-abortcontroller-polyfill[9]

3.6.1 使用

(async?()?=>?{const?abortController?=?new?AbortController();setTimeout(()?=>?{abortController.abort();},?500);try?{await?delay6(1000,?{signal:?abortController.signal});}?catch?(error)?{//?500?milliseconds?laterconsole.log(error.name)//=>?'AbortError'} })();

3.6.2 實現(xiàn)

const?randomInteger?=?(minimum,?maximum)?=>?Math.floor((Math.random()?*?(maximum?-?minimum?+?1))?+?minimum);const?createAbortError?=?()?=>?{const?error?=?new?Error('Delay?aborted');error.name?=?'AbortError';return?error; };const?createDelay?=?({willResolve})?=>?(ms,?{value,?signal}?=?{})?=>?{if?(signal?&&?signal.aborted)?{return?Promise.reject(createAbortError());}let?timeoutId;let?settle;let?rejectFn;const?signalListener?=?()?=>?{clearTimeout(timeoutId);rejectFn(createAbortError());}const?cleanup?=?()?=>?{if?(signal)?{signal.removeEventListener('abort',?signalListener);}};const?delayPromise?=?new?Promise((resolve,?reject)?=>?{settle?=?()?=>?{cleanup();if?(willResolve)?{resolve(value);}?else?{reject(value);}};rejectFn?=?reject;timeoutId?=?setTimeout(settle,?ms);});if?(signal)?{signal.addEventListener('abort',?signalListener,?{once:?true});}delayPromise.clear?=?()?=>?{clearTimeout(timeoutId);timeoutId?=?null;settle();};return?delayPromise; }const?createWithTimers?=?()?=>?{const?delay?=?createDelay({willResolve:?true});delay.reject?=?createDelay({willResolve:?false});delay.range?=?(minimum,?maximum,?options)?=>?delay(randomInteger(minimum,?maximum),?options);return?delay; } const?delay6?=?createWithTimers();

3.7 第七版 自定義 clearTimeout 和 setTimeout 函數(shù)

3.7.1 使用

const?customDelay?=?delay7.createWithTimers({clearTimeout,?setTimeout});(async()?=>?{const?result?=?await?customDelay(100,?{value:?'我是若川'});//?Executed?after?100?millisecondsconsole.log(result);//=>?'我是若川' })();

3.7.2 實現(xiàn)

傳遞 clearTimeout, setTimeout 兩個參數(shù)替代上一版本的clearTimeout,setTimeout。于是有了第七版。這也就是delay的最終實現(xiàn)。

const?randomInteger?=?(minimum,?maximum)?=>?Math.floor((Math.random()?*?(maximum?-?minimum?+?1))?+?minimum);const?createAbortError?=?()?=>?{const?error?=?new?Error('Delay?aborted');error.name?=?'AbortError';return?error; };const?createDelay?=?({clearTimeout:?defaultClear,?setTimeout:?set,?willResolve})?=>?(ms,?{value,?signal}?=?{})?=>?{if?(signal?&&?signal.aborted)?{return?Promise.reject(createAbortError());}let?timeoutId;let?settle;let?rejectFn;const?clear?=?defaultClear?||?clearTimeout;const?signalListener?=?()?=>?{clear(timeoutId);rejectFn(createAbortError());}const?cleanup?=?()?=>?{if?(signal)?{signal.removeEventListener('abort',?signalListener);}};const?delayPromise?=?new?Promise((resolve,?reject)?=>?{settle?=?()?=>?{cleanup();if?(willResolve)?{resolve(value);}?else?{reject(value);}};rejectFn?=?reject;timeoutId?=?(set?||?setTimeout)(settle,?ms);});if?(signal)?{signal.addEventListener('abort',?signalListener,?{once:?true});}delayPromise.clear?=?()?=>?{clear(timeoutId);timeoutId?=?null;settle();};return?delayPromise; }const?createWithTimers?=?clearAndSet?=>?{const?delay?=?createDelay({...clearAndSet,?willResolve:?true});delay.reject?=?createDelay({...clearAndSet,?willResolve:?false});delay.range?=?(minimum,?maximum,?options)?=>?delay(randomInteger(minimum,?maximum),?options);return?delay; } const?delay7?=?createWithTimers(); delay7.createWithTimers?=?createWithTimers;

4. axios 取消請求

axios取消原理是:通過傳遞 config 配置 cancelToken 的形式,來取消的。判斷有傳cancelToken,在 promise 鏈?zhǔn)秸{(diào)用的 dispatchRequest 拋出錯誤,在 adapter 中 request.abort() 取消請求,使 promise 走向 rejected,被用戶捕獲取消信息。

更多查看我的 axios 源碼文章取消模塊 學(xué)習(xí) axios 源碼整體架構(gòu),取消模塊(可點擊)

5. 總結(jié)

我們從零開始實現(xiàn)了一個帶取消功能比較完善的延遲函數(shù)。也就是 delay 70多行源碼[11]的實現(xiàn)。

包含支持隨機時間結(jié)束、提前清除、取消、自定義 clearTimeout、setTimeout等功能。

取消使用了 mdn AbortController[12] ,由于兼容性不太好,社區(qū)也有了相應(yīng)的 npm abort-controller[13] 實現(xiàn) polyfill。

yet-another-abortcontroller-polyfill[14]

建議克隆項目啟動服務(wù)調(diào)試例子,印象會更加深刻。

#?推薦克隆我的項目,保證與文章同步 git?clone?https://github.com/lxchuan12/delay-analysis.git cd?delay-analysis #?我寫的例子都在?examples?這個文件夾中,可以啟動服務(wù)本地查看調(diào)試 npx?http-server?examples #?打開?http://localhost:8080

最后可以持續(xù)關(guān)注我@若川。歡迎加我微信 ruochuan12 交流,參與 源碼共讀 活動,每周大家一起學(xué)習(xí)200行左右的源碼,共同進步。

參考資料

[1]

本文倉庫 https://github.com/lxchuan12/delay-analysis.git,求個star^_^: https://github.com/lxchuan12/delay-analysis.git

[2]

delay 主文件僅70多行: https://github.com/sindresorhus/delay/blob/main/index.js



更多點擊閱讀原文查看。

·················?若川簡介?·················

你好,我是若川,畢業(yè)于江西高校。現(xiàn)在是一名前端開發(fā)“工程師”。寫有《學(xué)習(xí)源碼整體架構(gòu)系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結(jié),已經(jīng)寫了7篇,點擊查看年度總結(jié)。
同時,最近組織了源碼共讀活動,幫助3000+前端人學(xué)會看源碼。公眾號愿景:幫助5年內(nèi)前端人走向前列。

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

總結(jié)

以上是生活随笔為你收集整理的面试官:请手写一个带取消功能的延迟函数,axios 取消功能的原理是什么的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。