http://nodejs.cn/learn/the-nodejs-event-loop
消息队列当调用 setTimeout() 时,浏览器或 Node.js 会启动定时器。 当定时器到期时(在此示例中会立即到期,因为将超时值设为 0),则回调函数会被放入“消息队列”中。 在消息队列中,用户触发的事件(如单击或键盘事件、或获取响应)也会在此排队,然后代码才有机会对其作出反应。 类似 onLoad 这样的 DOM 事件也如此。 事件循环会赋予调用堆栈优先级,它首先处理在调用堆栈中找到的所有东西,一旦其中没有任何东西,便开始处理消息队列中的东西。 我们不必等待诸如 setTimeout、fetch、或其他的函数来完成它们自身的工作,因为它们是由浏览器提供的,并且位于它们自身的线程中。 例如,如果将 setTimeout 的超时设置为 2 秒,但不必等待 2 秒,等待发生在其他地方。 ES6 作业队列ECMAScript 2015 引入了作业队列的概念,Promise 使用了该队列(也在 ES6/ES2015 中引入)。 这种方式会尽快地执行异步函数的结果,而不是放在调用堆栈的末尾。 在当前函数结束之前 resolve 的 Promise 会在当前函数之后被立即执行。 有个游乐园中过山车的比喻很好:消息队列将你排在队列的后面(在所有其他人的后面),你不得不等待你的回合,而工作队列则是快速通道票,这样你就可以在完成上一次乘车后立即乘坐另一趟车。 示例: [color=var(--black9)][backcolor=var(--black3)]JS
[color=var(--info3) !important]const [color=var(--warning3) !important]bar [color=var(--black2) !important]= [color=var(--black2) !important]([color=var(--black2) !important]) [color=var(--black2) !important]=> console[color=var(--black2) !important].[color=var(--warning3) !important]log[color=var(--black2) !important]([color=var(--brand3) !important]'bar'[color=var(--black2) !important])
[color=var(--info3) !important]const [color=var(--warning3) !important]baz [color=var(--black2) !important]= [color=var(--black2) !important]([color=var(--black2) !important]) [color=var(--black2) !important]=> console[color=var(--black2) !important].[color=var(--warning3) !important]log[color=var(--black2) !important]([color=var(--brand3) !important]'baz'[color=var(--black2) !important])
[color=var(--info3) !important]const [color=var(--warning3) !important]foo [color=var(--black2) !important]= [color=var(--black2) !important]([color=var(--black2) !important]) [color=var(--black2) !important]=> [color=var(--black2) !important]{
console[color=var(--black2) !important].[color=var(--warning3) !important]log[color=var(--black2) !important]([color=var(--brand3) !important]'foo'[color=var(--black2) !important])
[color=var(--warning3) !important]setTimeout[color=var(--black2) !important](bar[color=var(--black2) !important], [color=var(--purple3) !important]0[color=var(--black2) !important])
[color=var(--info3) !important]new Promise[color=var(--black2) !important]([color=var(--black2) !important](resolve[color=var(--black2) !important], reject[color=var(--black2) !important]) [color=var(--black2) !important]=>
[color=var(--warning3) !important]resolve[color=var(--black2) !important]([color=var(--brand3) !important]'应该在 baz 之后、bar 之前'[color=var(--black2) !important])
[color=var(--black2) !important])[color=var(--black2) !important].[color=var(--warning3) !important]then[color=var(--black2) !important](resolve [color=var(--black2) !important]=> console[color=var(--black2) !important].[color=var(--warning3) !important]log[color=var(--black2) !important](resolve[color=var(--black2) !important])[color=var(--black2) !important])
[color=var(--warning3) !important]baz[color=var(--black2) !important]([color=var(--black2) !important])
[color=var(--black2) !important]}
[color=var(--warning3) !important]foo[color=var(--black2) !important]([color=var(--black2) !important])
这会打印: [color=var(--black9)][backcolor=var(--black3)]TXT
foo
baz
应该在 baz 之后、bar 之前
bar
这是 Promise(以及基于 promise 构建的 async/await)与通过 setTimeout() 或其他平台 API 的普通的旧异步函数之间的巨大区别。
|