Promise vs setTimeout

时间:2016-08-03 20:01:40

标签: javascript asynchronous

我在以下代码中观察到:

setTimeout(function(){console.log('setTimeout')});
Promise.resolve(1).then(function(){console.log('promise resolve')})

无论执行多少次,promise回调总是在setTimeout之前记录。

我的理解是,两个回调都安排在下一个时间点执行,而且我真的不明白发生了什么,这使得承诺总是优先于超时。

6 个答案:

答案 0 :(得分:23)

Promise.resolve安排一个微任务,setTimeout安排一个macrotask。并且在运行下一个macrotask之前执行微任务。

答案 1 :(得分:16)

简短回答Promise比事件循环堆栈中的setTimeout回调函数(或我如何理解)具有更好的优先级。

长时间回答观看此视频。很有帮助。希望这会有所帮助。

https://www.youtube.com/watch?v=8aGhZQkoFbQ

感谢@MickJuice提供有关事件循环的新视频和更新视频。

https://www.youtube.com/watch?v=cCOL7MC4Pl0

答案 2 :(得分:13)

git add --force file.conf有一个minimum delay of 4ms,所以即使您没有在代码中指定延迟,超时仍会延迟至少4毫秒。在此期间,您的承诺setTimeout()被调用。

答案 3 :(得分:3)

超时承诺均以异步方式执行代码,但具有不同的特征和目的:

setTimeout -将功能执行延迟特定的持续时间。 -不阻止其余代码执行(异步行为) -他们创建Macrotask(浏览器内部操作)

承诺 -它们是允许异步执行代码的包装器(例如ajax调用)。 (不取决于特定的持续时间) -它们对于链接不同的异步调用特别有用。 -减少您使用await运算符的时间,不会阻塞其余的代码执行(异步行为)。 -他们创建了 Microtask (浏览器内部操作),其优先级高于 Macrotask

推荐

  • 如果要延迟某个特定时间的函数执行,而又不阻塞进程中其余代码的执行,请使用 setTimeout

  • 使用承诺: 当您想执行一些异步代码并避免“回调地狱”(是的,因为您可以在没有Promises的情况下进行异步ajax调用,但是语法不太清晰,更容易出错)

答案 4 :(得分:3)

这与Web Spec中定义的事件循环有关。浏览器有多个任务队列用于处理多种类型的任务(例如,通过setTimeout创建的计时器任务),以及 microtask队列(其中承诺承诺得到推送)至)。每当浏览器完成执行 任务时,它就会清空微任务队列并执行其中的所有任务,然后再继续执行另一个任务队列中的任务。

因此,在执行代码(这是一个任务)之后,Promise解决方案将位于微任务队列中,而计时器任务可能已位于任务队列中¹。微任务队列被清空,并且Promise解决。然后在计时器任务运行时。

¹浏览器可能会选择增加超时时间,但确实如此。在大多数浏览器中,超时永远不会在0毫秒后运行。

答案 5 :(得分:2)

超时和承诺有不同的目的。

setTimeout将代码块的执行延迟特定的持续时间。 Promises是允许异步执行代码的接口。

承诺允许代码在您等待其他操作完成时继续执行。通常这是一个网络电话。因此,一旦网络呼叫(或任何等待的承诺)完成,您的then()呼叫中的任何内容都将被执行。承诺的开始和承诺的解决之间的时间差完全取决于承诺执行的内容,并且可以随着每次执行而改变。

承诺在超时之前执行的原因是承诺实际上没有等待任何事情,所以它立即解决了。