日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

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

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

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

閱讀本文,你將學到:

1.?學會如何實現一個比較完善的?delay?函數 2.?學會使用?AbortController?實現取消功能 3.?學會面試常考?axios?取消功能實現 4.?等等

2. 環境準備

#?推薦克隆我的項目,保證與文章同步 git?clone?https://github.com/lxchuan12/delay-analysis.git #?npm?i?-g?yarn cd?delay-analysis/delay?&&?yarn?i #?VSCode?直接打開當前項目 #?code?. #?我寫的例子都在?examples?這個文件夾中,可以啟動服務本地查看調試 #?在?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?直接打開當前項目 #?code?.

3. delay

我們從零開始來實現一個比較完善的 delay 函數[3]

3.1 第一版 簡版延遲

要完成這樣一個延遲函數。

3.1.1 使用

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

3.1.2 實現

用 Promise 和 setTimeout 結合實現,我們都很容易實現以下代碼。

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

我們要傳遞結果。

3.2 第二版 傳遞 value 參數作為結果

3.2.1 使用

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

我們也很容易實現如下代碼。傳遞 value 最后作為結果返回。

3.2.2 實現

因此我們實現也很容易實現如下第二版。

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

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

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

3.3.1 使用

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

3.3.2 實現

加個 willResolve 參數決定成功還是失敗。于是我們有了如下實現。

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

3.4 第四版 一定時間范圍內隨機獲得結果

延時器的毫秒數是寫死的。我們希望能夠在一定時間范圍內隨機獲取到結果。

3.4.1 使用

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

3.4.2 實現

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

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();

實現到這里,相對比較完善了。但我們可能有需要提前結束。

3.5 第五版 提前清除

3.5.1 使用

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

3.5.2 實現

聲明 settle變量,封裝 settle 函數,在調用 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 可以實現取消功能。

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 實現

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 函數

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 實現

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

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 鏈式調用的 dispatchRequest 拋出錯誤,在 adapter 中 request.abort() 取消請求,使 promise 走向 rejected,被用戶捕獲取消信息。

更多查看我的 axios 源碼文章取消模塊 學習 axios 源碼整體架構,取消模塊(可點擊)

5. 總結

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

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

取消使用了 mdn AbortController[12] ,由于兼容性不太好,社區也有了相應的 npm abort-controller[13] 實現 polyfill。

yet-another-abortcontroller-polyfill[14]

建議克隆項目啟動服務調試例子,印象會更加深刻。

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

最后可以持續關注我@若川。歡迎加我微信 ruochuan12 交流,參與 源碼共讀 活動,每周大家一起學習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



更多點擊閱讀原文查看。

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

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

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

今日話題

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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。