我试图制作一个延迟X毫秒执行异步函数的函数。
为了演示的目的,以下是异步函数,该函数采用URL:
/* * This is a simulation of an async function. Be imaginative! */ let asyncMock = function(url) { return new Promise(fulfil => { setTimeout(() => { fulfil({ url, data: "banana" }); }, 10000); }); };
我在这里的目标是要有一个函数,它将接受X 的url参数,asyncMock然后每隔X ms调用一次,直到不再有其他参数为止。
url
asyncMock
基本上,我希望每次调用都asyncMock用X ms分隔。
例如,假设我asyncMock连续打电话20次。通常,这20个呼叫将立即进行。我想要的是确保20个呼叫之间都存在Xms的延迟。
解决这个问题的想法是建立一个工厂,该工厂将返回一个承诺,该承诺将在X ms之后执行该功能。
let throttleFactory = function(args) { let { throttleMs } = args; let promise = Promise.resolve(); let throttleAsync = function(url) { return promise.then(() => { setTimeout(anUrl => { return new Promise( fulfil => { fulfil(asyncMock(anUrl)); }); }, throttleMs, url); }); }; return Object.freeze({ throttleAsync }); };
理想情况下,我将在下面的示例中使用该工厂:
let throttleFuns = throttleFactory({ throttleMs: 2000 }); console.log('running'); throttleFuns.throttleAsync('http://www.bananas.pt') .then(console.log) .catch(console.error); throttleFuns.throttleAsync('http://www.fruits.es') .then(console.log) .catch(console.error); throttleFuns.throttleAsync('http://www.veggies.com') .then(console.log) .catch(console.error); // a ton of other calls in random places in code
这里的问题是我的throttleAsync功能undefined立即输出3次。我相信这可能是因为我没有promise正确定义。
throttleAsync
undefined
promise
如何修复此代码以使其正常工作?
因为throttleAsync返回调用的结果promise.then,并且then回调不返回任何内容。这使得通过then解决创造的承诺具有价值undefined。
promise.then
then
您可能打算让它返回您正在创建的新的Promise,但是直到setTimeout回调之前您都不会这样做。您想事先做(但还有更多,请继续阅读):
setTimeout
let throttleAsync = function(url) { return promise.then(() => { return new Promise( fulfil => { setTimeout(anUrl => { fulfil(asyncMock(anUrl)); }, throttleMs, url); }); }); };
也没有理由setTimeout像这样传递URL ,因此:
let throttleAsync = function(url) { return promise.then(() => { return new Promise( fulfil => { setTimeout(() => { fulfil(asyncMock(url)); }, throttleMs); }); }); };
最初,我虽然promise没有必要,但是您已经澄清了,您想确保重复的呼叫由隔开throttleMs。为此,我们将使用上面的方法,但要进行更新promise:
throttleMs
let throttleAsync = function(url) { return promise = promise.then(() => { // ^^^^^^^^^ return new Promise( fulfil => { setTimeout(() => { fulfil(asyncMock(url)); }, throttleMs); }); }); };
这样,下一个呼叫asyncThrottle将一直等到前一个触发后再开始下一个。
asyncThrottle
现场示例:
const throttleMs = 1000; const asyncMock = url => url; let promise = Promise.resolve(); let throttleAsync = function(url) { return promise = promise.then(() => { // ^^^^^^^^^ return new Promise( fulfil => { setTimeout(() => { fulfil(asyncMock(url)); }, throttleMs); }); }); }; console.log('running'); throttleAsync('http://www.bananas.pt') .then(console.log) .catch(console.error); throttleAsync('http://www.fruits.es') .then(console.log) .catch(console.error); throttleAsync('http://www.veggies.com') .then(console.log) .catch(console.error);