Promise.resolve().then vs setImmediate vs nextTick

Posted

技术标签:

【中文标题】Promise.resolve().then vs setImmediate vs nextTick【英文标题】: 【发布时间】:2015-02-23 05:04:52 【问题描述】:

NodeJS 0.11 以及 io.js 和 Node 0.12 分支都附带原生承诺。

Native 承诺 have a .then method 始终在未来的事件循环周期中执行。

到目前为止,自从我 switched from nextTick 以来,我一直在使用 setImmediate 将事情排队到事件循环的下一次迭代:

setImmediate(deferThisToNextTick); // My NodeJS 0.10 code
process.nextTick(deferThisToNextTick); // My NodeJS 0.8 code

因为我们现在有了一种新的方法来做到这一点:

Promise.resolve().then(deferThisToNextTick); 

我应该使用哪个?另外 - 关于在事件循环之前或之后运行的代码,Promise.resolve.then 是否像 setImmediatenextTick 一样?

【问题讨论】:

分享一些研究:在 Chromium 中 - 一个承诺将一个微任务排入队列,这里运行微任务 github.com/yoavweiss/Blink/blob/… 当脚本到达或检查并且没有脚本运行时调用这里:github.com/yoavweiss/Blink/blob/… 承诺解决github.com/joyent/node/blob/… - 调用github.com/joyent/node/blob/… - 到达github.com/joyent/node/blob/… 非常相关:github.com/joyent/node/issues/7714 更多酱汁:github.com/joyent/node/blob/v0.12/src/node.js#L305 经过验证的微任务在 nextTick 队列上运行:github.com/joyent/node/blob/v0.12/src/node.js#L326-L329,将等待几个小时,看看 v8 或节点团队成员是否愿意澄清,如果没有,我会写下我的答案。跨度> 【参考方案1】:

Promise.resolve 将立即(同步地)解决,而 setImmediate 在当前事件执行后立即显式解决。

【讨论】:

在你的浏览器控制台中试试看你错了:Promise.resolve([]).then(function() console.log('1'); ); console.log('2'); 我认为您将它与新的Promise((res, rej) => res()); 混淆了。上面的例子new Promise((res) => console.log(1); res(); ); console.log(2);。在这种情况下,1 将在 2 之前打印。【参考方案2】:

我不打算回答有关技术细节的粗体部分,而只回答问题

我应该使用哪个?

我认为没有任何理由使用Promise.resolve().then(),除非您对异步执行函数的结果的承诺感兴趣。当然,如果您,那么这将远远优于处理回调地狱或从setTimeoutnextTick 制作new Promise

还有第二个技术差异,比时间更重要:promise 会吞下异常。你可能不想要。所以,就像@vkurchatkin 提到的那样,不要创建承诺只是为了把它们扔掉。不仅因为它速度较慢,还因为它使您的代码可读性降低,并且您的应用更容易出错。

【讨论】:

【参考方案3】:

使用Promise.resolve().thennextTick 相比没有任何优势。它在同一个队列上运行,但优先级略高,也就是说,promise handler 可以阻止 next tick 回调永远运行,相反是不可能的。此行为是一个实现细节,不应依赖。

Promise.resolve().then 显然更慢(我认为很多),因为它创建了两个将被丢弃的 Promise。

您可以在此处找到详细的实施信息:https://github.com/joyent/node/pull/8325

最重要的部分:Promise.resolve().then 类似于nextTick 而不是setImmediate。使用它代替setImmediate 可以极大地改变您的代码行为。

【讨论】:

赞成。我很想看到最后一段的例子。 谢谢,这听起来很正确,而且我在代码中也观察到了。如果您能详细说明何时使用其中任何一个以及为什么它会以这种方式工作,那就太好了。 @thefourtheye 任何 nextTick 不能代替 setImmediate 工作的例子 - Promise.resolve().then 也不能工作 我的意思是你根本不应该使用Promise.resolve().then。这个伎俩一事无成。关于 nextTick 与 setImmediate 有很多信息 “它在同一个队列上运行,但优先级略高......” 实际上,并非如此。每个都有自己的机制来处理回调队列。 嗯,微任务队列在nextTick 队列中被刷新,这就是我的意思。目的是让这个行为尽可能像一个队列

以上是关于Promise.resolve().then vs setImmediate vs nextTick的主要内容,如果未能解决你的问题,请参考以下文章

为啥链接到 Promise.resolve() 的 .then() 允许重新分配 const 声明?

正确使用 Promise.resolve().then() 错误:未捕获(在承诺中):TypeError:无法读取属性

promise-then执行顺序问题

promise 个人练习

Promise对象

promise/async/await