摘要:考慮如下代碼如果用戶在和之間再次點(diǎn)擊的話,就有可能同時發(fā)出兩個。這是個很合理的需求,所以我特意在上提問,可惜看起來并沒有現(xiàn)成的輪子可以用。用下面的函數(shù)包裹原函數(shù),如果前一次請求尚未結(jié)束,新請求會排隊(duì)。示例使用以上所有代碼按授權(quán)。
考慮如下代碼
whatever.onclick = async () => { const a = await(await fetch("step-1")).text(); const b = await(await fetch("step-2")).text(); whatever.textContent = a + b; }
如果用戶在step-1和step-2之間再次點(diǎn)擊的話,就有可能同時發(fā)出兩個step-1。
當(dāng)然,服務(wù)器可以驗(yàn)證之后通通拒掉,但是用戶體驗(yàn)很差。這是個很合理的需求,所以我特意在SF上提問,可惜看起來并沒有現(xiàn)成的輪子可以用。
所以還是只能自己造。
用下面的函數(shù)包裹原函數(shù),如果前一次請求尚未結(jié)束,新請求會和舊請求一起返回。
/** * Creates a function that invokes `originalFunction`, with the `this` binding * and `arguments` of the created function, while there is no other pending * excutions of `originalFunction`. Simultaneous calls to the created function * return the result of the first pending `originalFunction` invocation. * * @param {function} originalFunction async function to wrap */ const debounceAsync = originalFunction => { let currentExcution = null; const wrappedFunction = async function () { // 1. locked => return lock if (currentExcution) return currentExcution; // 2. released => apply currentExcution = originalFunction.apply(this, arguments); try { return await currentExcution; } finally { currentExcution = null; } }; return wrappedFunction; };
用下面的函數(shù)包裹原函數(shù),如果前一次請求尚未結(jié)束,新請求會排隊(duì)。
const endOfQueue = Promise.resolve(); const overrideResult = async lastExcution => { try { await lastExcution; } finally { return endOfQueue; } } /** * Creates a function that invokes `originalFunction`, with the `this` binding * and `arguments` of the created function, while there is no other pending * excutions of `originalFunction`. Simultaneous calls to the created function * will be queued up. * * @param {function} originalFunction async function to wrap */ const queueAsync = originalFunction => { let lastExcution = endOfQueue; const wrappedFunction = async function () { // 1. queue up const myExcution = lastExcution.then(() => originalFunction.apply(this, arguments)); // 2. update queue tail + swipe excution result from queue lastExcution = overrideResult(myExcution); // 3. return excution result return myExcution; }; return wrappedFunction; }
示例使用
/** * A promisified settimeout * * @param {number} [ms=0] time to sleep in ms */ const sleep = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); const debounceAsync_UNIT_TEST = async () => { const goodnight = debounceAsync(sleep); for (let i = 0; i < 8; i++) { goodnight(5000).then(() => console.log(Date())); await sleep(500); } console.warn("Expected output: 8 identical datetime"); }; const queueAsync_UNIT_TEST = () => { const badnight = queueAsync(i => sleep(i).then(() => { if (Math.random() > 0.5) throw new Error("uncaught error test: you should expect a console error message.") })); badnight(1000); badnight(1000); badnight(1000); badnight(1000); badnight(1000).finally(() => console.log("5s!")); badnight(1000); badnight(1000); badnight(1000); badnight(1000); badnight(1000).finally(() => console.log("10s!")); console.warn("Check message timestamps."); console.warn("Bad:"); console.warn("1 1 1 1 1:5s"); console.warn(" 1 1 1 1 1:10s"); console.warn("Good:"); console.warn("1 1 1 1 1:5s"); console.warn(" 1 1 1 1 1:10s"); }
以上所有代碼按Mozilla Public License, v. 2.0授權(quán)。
以上所有文字內(nèi)容按CC BY-NC-ND 4.0授權(quán)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/95456.html
摘要:瀏覽器的渲染進(jìn)程是多線程的。異步請求線程在在連接后是通過瀏覽器新開一個線程請求將檢測到狀態(tài)變更時,如果設(shè)置有回調(diào)函數(shù),異步線程就產(chǎn)生狀態(tài)變更事件,將這個回調(diào)再放入事件隊(duì)列中。 [TOC] 瀏覽器進(jìn)程線程 區(qū)分線程和進(jìn)程 **- 什么是進(jìn)程** 狹義定義:進(jìn)程是正在運(yùn)行的程序的實(shí)例(an instance of a computer program that is being exe...
摘要:解析首先簡稱是由歐洲計(jì)算機(jī)制造商協(xié)會制定的標(biāo)準(zhǔn)化腳本程序設(shè)計(jì)語言。級在年月份成為的提議,由核心與兩個模塊組成。通過引入統(tǒng)一方式載入和保存文檔和文檔驗(yàn)證方法對進(jìn)行進(jìn)一步擴(kuò)展。其中表示的標(biāo)記位正好是低三位都是。但提案被拒絕了。 JS高級入門教程 目錄 本文章定位及介紹 JavaScript與ECMAScript的關(guān)系 DOM的本質(zhì)及DOM級介紹 JS代碼特性 基本類型與引用類型 JS的垃...
摘要:的單線程,與它的用途有關(guān)。特點(diǎn)的顯著特點(diǎn)異步機(jī)制事件驅(qū)動。隊(duì)列的讀取輪詢線程,事件的消費(fèi)者,的主角。它將不同的任務(wù)分配給不同的線程,形成一個事件循環(huán),以異步的方式將任務(wù)的執(zhí)行結(jié)果返回給引擎。 這兩天跟同事同事討論遇到的一個問題,js中的event loop,引出了chrome與node中運(yùn)行具有setTimeout和Promise的程序時候執(zhí)行結(jié)果不一樣的問題,從而引出了Nodejs的...
摘要:若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時刻內(nèi)只能執(zhí)行特定的一個任務(wù),并且會阻塞其它任務(wù)執(zhí)行。瀏覽器事件觸發(fā)線程事件觸發(fā)線程,當(dāng)一個事件被觸發(fā)時該線程會把事件添加到任務(wù)隊(duì)列的隊(duì)尾,等待引擎的處理。 首先,說下為什么 JavaScript 是單線程? 總所周知,JavaScript是以單線程的方式運(yùn)行的。說到線程就自然聯(lián)想到進(jìn)程。那它們有什么聯(lián)系呢? ...
摘要:標(biāo)簽單線程首發(fā)地址碼農(nóng)網(wǎng)細(xì)說單線程的一些事最近被同學(xué)問道單線程的一些事,我竟回答不上。若以多線程的方式操作這些,則可能出現(xiàn)操作的沖突。另外,因?yàn)槭菃尉€程的,在某一時刻內(nèi)只能執(zhí)行特定的一個任務(wù),并且會阻塞其它任務(wù)執(zhí)行。 標(biāo)簽: JavaScript 單線程 首發(fā)地址:碼農(nóng)網(wǎng)《細(xì)說JavaScript單線程的一些事》 最近被同學(xué)問道 JavaScript 單線程的一些事,我竟回答不上。好...
閱讀 2158·2021-09-22 10:56
閱讀 1465·2021-09-07 10:11
閱讀 1801·2019-08-30 15:54
閱讀 2290·2019-08-30 15:44
閱讀 2307·2019-08-29 12:40
閱讀 3031·2019-08-28 18:25
閱讀 1735·2019-08-26 10:24
閱讀 3186·2019-08-23 18:39