Javascript 如何重写forEach以使用“承诺停止”;冻结“;浏览器?

Javascript 如何重写forEach以使用“承诺停止”;冻结“;浏览器?,javascript,ecmascript-6,es6-promise,Javascript,Ecmascript 6,Es6 Promise,我有一个函数,看起来像这样 function () { longArray.forEach( element => doSomethingResourceIntensive(element)) } 因为数组很长,而且函数有点资源密集型,所以会冻结浏览器 现在我想用Promissions重写它,所以它做同样的事情,只是不冻结浏览器,我希望解决方案优雅且“ES6-y”;理想情况下,当所有迭代完成时,函数将返回Promise 我发现,它是使用setTimeout处理的,但它似乎

我有一个函数,看起来像这样

 function () {
      longArray.forEach( element => doSomethingResourceIntensive(element))
 }
因为数组很长,而且函数有点资源密集型,所以会冻结浏览器

现在我想用Promissions重写它,所以它做同样的事情,只是不冻结浏览器,我希望解决方案优雅且“ES6-y”;理想情况下,当所有迭代完成时,函数将返回Promise

我发现,它是使用setTimeout处理的,但它似乎有点“un-ES6-y”,并且它不返回承诺

我做不到

 function () {
      return Promise.all(longArray.map( element => 
          Promise.resolve().then(() => doSomethingResourceIntensive(element))
      )
 }

因为我需要连续运行承诺,我不确定它是否会在那里发生。

如果需要连续运行承诺,您希望链接
。然后
调用。您通常使用执行此操作:

function () {
    return longArray.reduce((promise, el) => 
        promise.then(() => doSomethingResourceIntensive(el)),
      Promise.resolve()); // Start with a clean promise!
}

此外,根据您所做的作业类型,您可能需要查看,这些作业在另一个线程中执行,因此不会阻塞页面。

您引用的答案是正确的,您需要
设置超时。仅使用承诺链是没有帮助的,因为
。然后,
链在微任务队列上执行,在大多数浏览器中,微任务队列在当前运行结束时被完全清空。换句话说,他们仍然会冻结东西

如果你想要ES6-y的东西,我依靠这个可靠的助手:

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
然后我可以这样做:

longArray.reduce((p, i) => p.then(() => doIntensiveStuff(i)).then(() => wait(5)),
                 Promise.resolve());

当然,除非您可以使用worker。

您是否尝试使用
setTimeout
并在内部执行循环?如何?承诺是处理异步操作的一种方法,它们不会神奇地阻止长时间运行的JavaScript冻结浏览器。您必须以非阻塞方式重写代码,例如使用web workers或使用
setTimeout
/
setImmediate
@PaoloMoretti Hm,是的,但至少当我添加了自己的函数
timeoutPromise
(这正是您所期望的)时,它实际上开始超时,并且工作得相当好,虽然看起来仍然优雅,但无论是承诺还是超时都无法阻止浏览器冻结。代码仍然必须运行。使用超时可以实现的唯一一件事是对工作负载进行分区,如果工作单元足够小,这将是一种改进。Web workers是处理大型工作负载的唯一解决方案,因为他们将工作转移到另一个线程。这看起来很有希望(没有双关语),我可能会使用这个。我想你错过了
承诺之前的
返回
。然后
@Sean不,我只是有多余的花括号和分号。艺龙网胡胡函数句柄句柄只有一个状态返回。你认为在小的块中分割长数组会更好吗?并且用承诺处理块。它已经有了那个助手(名为
Promise.delay()
)和许多非常有用的特性。