I have a function, that looks like this.
function () {
longArray.forEach( element => doSomethingResourceIntensive(element))
}
Because the array is long and the function is a little resource intensive, it freezes the browser.
Now I want to rewrite it using Promises, so it does the same thing, just not freezing the browser, and I want the solution to be elegant and "ES6-y"; ideally, the function would return Promise when all the iterations finished.
I found this question, where it's dealt with using setTimeout, but it seems a little "un-ES6-y", and it doesn't return a Promise.
I cannot do
function () {
return Promise.all(longArray.map( element =>
Promise.resolve().then(() => doSomethingResourceIntensive(element))
)
}
because I need to run the promises in succession and I am not sure if it would happen there.
答案 0 :(得分:4)
If you need to run promises in succession, you want to chain the .then
calls. You normally do that with .reduce()
:
function () {
return longArray.reduce((promise, el) =>
promise.then(() => doSomethingResourceIntensive(el)),
Promise.resolve()); // Start with a clean promise!
}
Also, depending on the type of job you do, you may want to have a look into Web Workers, which are executed in another thread and thus don't block the page.
答案 1 :(得分:1)
您引用的答案是正确的,您需要setTimeout
。单独使用promise链不会有帮助,因为.then
链在微任务队列上执行,在大多数浏览器中,在当前的run-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());
除非你当然可以使用工人。