如何重写 forEach 以使用 Promises 停止 "freezing" 浏览器?
How to rewrite forEach to use Promises to stop "freezing" browsers?
我有一个函数,看起来像这样。
function () {
longArray.forEach( element => doSomethingResourceIntensive(element))
}
由于数组长,函数占用资源少,导致浏览器卡顿
现在我想用 Promises 重写它,所以它做同样的事情,只是不冻结浏览器,我希望解决方案优雅 "ES6-y";理想情况下,该函数将 return Promise 当所有迭代完成时。
我找到了this question,这里是用setTimeout处理的,不过好像有点"un-ES6-y",而且return不是Promise
我做不到
function () {
return Promise.all(longArray.map( element =>
Promise.resolve().then(() => doSomethingResourceIntensive(element))
)
}
因为我需要连续 运行 承诺,我不确定它是否会在那里发生。
如果您需要连续 运行 个承诺,您需要链接 .then
个调用。您通常使用 .reduce()
:
function () {
return longArray.reduce((promise, el) =>
promise.then(() => doSomethingResourceIntensive(el)),
Promise.resolve()); // Start with a clean promise!
}
此外,根据您从事的工作类型,您可能想查看 Web Workers,它们在另一个线程中执行,因此不会不要阻止页面。
您参考的答案是正确的,您需要setTimeout
。单独使用承诺链不会有帮助,因为 .then
链在微任务队列上执行,在大多数浏览器中,它在当前 运行-to-completion 的尾部被完全清空。换句话说,他们仍然会冻结东西。
如果你想要 ES6-y 的东西,我依赖这个可信赖的帮手:
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
那我可以这样做:
longArray.reduce((p, i) => p.then(() => doIntensiveStuff(i)).then(() => wait(5)),
Promise.resolve());
除非你当然可以使用工人。
我有一个函数,看起来像这样。
function () {
longArray.forEach( element => doSomethingResourceIntensive(element))
}
由于数组长,函数占用资源少,导致浏览器卡顿
现在我想用 Promises 重写它,所以它做同样的事情,只是不冻结浏览器,我希望解决方案优雅 "ES6-y";理想情况下,该函数将 return Promise 当所有迭代完成时。
我找到了this question,这里是用setTimeout处理的,不过好像有点"un-ES6-y",而且return不是Promise
我做不到
function () {
return Promise.all(longArray.map( element =>
Promise.resolve().then(() => doSomethingResourceIntensive(element))
)
}
因为我需要连续 运行 承诺,我不确定它是否会在那里发生。
如果您需要连续 运行 个承诺,您需要链接 .then
个调用。您通常使用 .reduce()
:
function () {
return longArray.reduce((promise, el) =>
promise.then(() => doSomethingResourceIntensive(el)),
Promise.resolve()); // Start with a clean promise!
}
此外,根据您从事的工作类型,您可能想查看 Web Workers,它们在另一个线程中执行,因此不会不要阻止页面。
您参考的答案是正确的,您需要setTimeout
。单独使用承诺链不会有帮助,因为 .then
链在微任务队列上执行,在大多数浏览器中,它在当前 运行-to-completion 的尾部被完全清空。换句话说,他们仍然会冻结东西。
如果你想要 ES6-y 的东西,我依赖这个可信赖的帮手:
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
那我可以这样做:
longArray.reduce((p, i) => p.then(() => doIntensiveStuff(i)).then(() => wait(5)),
Promise.resolve());
除非你当然可以使用工人。