摘要:考虑如下代码如果用户在和之间再次点击的话,就有可能同时发出两个。这是个很合理的需求,所以我特意在上提问,可惜看起来并没有现成的轮子可以用。用下面的函数包裹原函数,如果前一次请求尚未结束,新请求会排队。示例使用以上所有代码按授权。
考虑如下代码
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之间再次点击的话,就有可能同时发出两个step-1。
当然,服务器可以验证之后通通拒掉,但是用户体验很差。这是个很合理的需求,所以我特意在SF上提问,可惜看起来并没有现成的轮子可以用。
所以还是只能自己造。
用下面的函数包裹原函数,如果前一次请求尚未结束,新请求会和旧请求一起返回。
/** * 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; };
用下面的函数包裹原函数,如果前一次请求尚未结束,新请求会排队。
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授权。
以上所有文字内容按CC BY-NC-ND 4.0授权。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/95456.html
摘要:的单线程,与它的用途有关。特点的显著特点异步机制事件驱动。队列的读取轮询线程,事件的消费者,的主角。它将不同的任务分配给不同的线程,形成一个事件循环,以异步的方式将任务的执行结果返回给引擎。 这两天跟同事同事讨论遇到的一个问题,js中的event loop,引出了chrome与node中运行具有setTimeout和Promise的程序时候执行结果不一样的问题,从而引出了Nodejs的...
摘要:若以多线程的方式操作这些,则可能出现操作的冲突。另外,因为是单线程的,在某一时刻内只能执行特定的一个任务,并且会阻塞其它任务执行。浏览器事件触发线程事件触发线程,当一个事件被触发时该线程会把事件添加到任务队列的队尾,等待引擎的处理。 首先,说下为什么 JavaScript 是单线程? 总所周知,JavaScript是以单线程的方式运行的。说到线程就自然联想到进程。那它们有什么联系呢? ...
摘要:标签单线程首发地址码农网细说单线程的一些事最近被同学问道单线程的一些事,我竟回答不上。若以多线程的方式操作这些,则可能出现操作的冲突。另外,因为是单线程的,在某一时刻内只能执行特定的一个任务,并且会阻塞其它任务执行。 标签: JavaScript 单线程 首发地址:码农网《细说JavaScript单线程的一些事》 最近被同学问道 JavaScript 单线程的一些事,我竟回答不上。好...
阅读 2058·2021-09-22 10:56
阅读 1353·2021-09-07 10:11
阅读 1772·2019-08-30 15:54
阅读 2264·2019-08-30 15:44
阅读 2285·2019-08-29 12:40
阅读 3000·2019-08-28 18:25
阅读 1701·2019-08-26 10:24
阅读 3157·2019-08-23 18:39