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
是否像 setImmediate
或 nextTick
一样?
【问题讨论】:
分享一些研究:在 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()
,除非您对异步执行函数的结果的承诺感兴趣。当然,如果您是,那么这将远远优于处理回调地狱或从setTimeout
或nextTick
制作new Promise
。
还有第二个技术差异,比时间更重要:promise 会吞下异常。你可能不想要。所以,就像@vkurchatkin 提到的那样,不要创建承诺只是为了把它们扔掉。不仅因为它速度较慢,还因为它使您的代码可读性降低,并且您的应用更容易出错。
【讨论】:
【参考方案3】:使用Promise.resolve().then
与nextTick
相比没有任何优势。它在同一个队列上运行,但优先级略高,也就是说,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 声明?