在浏览器和节点之间EventLoop有什么区别?

时间:2017-11-11 22:30:49

标签: javascript node.js v8

Promise.resolve().then(() => {
  console.log('promise2')
  setTimeout(() => console.log('setTimeout2'))
})
setTimeout(() => {
  console.log('setTimeout1')
  Promise.resolve().then(() => console.log('promise1'))
})

在浏览器中运行代码的结果:

promise2 -> setTimeout1 -> promise1 -> setTimeout2

但在Node

promise2 -> setTimeout1 -> setTimeout2 ->promise1 

1 个答案:

答案 0 :(得分:0)

首先,讨论第三个陈述,并将匿名函数标识为t1t2f1f2作为计时器(t)和履行承诺(f)回调:

Promise.resolve().then(() => { // f2
  console.log('promise2')
  setTimeout(() => console.log('setTimeout2') /* t2 */)
})  // statement 1

setTimeout(() => {  // t1
  console.log('setTimeout1')
  Promise.resolve().then(() => console.log('promise1'/* f1 */) // statement 3
}  // statement 2

声明1将 1 f2置于承诺作业队列(PJQ)中, 假设Promise.resolve在其参数不是promise或者thenable时同步返回履行的promise。在履行的承诺上调用then会在调用期间将执行的处理程序执行到PJQ,以便稍后在处理承诺作业队列时执行。

语句2将t1置于定时器回调队列中。


1 执行时,承诺处理程序由执行程序代码监视thencatch返回的承诺。

<小时/> 在浏览器中处理队列,优先考虑promise作业队列:

PJQ:    f2
TimerQ: t1

调用f2,记录“promise2”,将t2添加到定时器队列

PJQ:     <empty>
Timers:  t1, t2

调用t1,记录“setTimeout1”,执行语句3,将f1添加到promise作业队列。

PJQ:    f1
Timers: t2

调用f1,记录“promise1”

PJQ:    <empty>
timers: t2

调用t2,记录“setTimeout2”。

因此,当promise作业队列的优先级高于计时器回调时,日志显示为“promise2”,“setTimeout1”,“promise1”,“setTimeout2”。

<小时/> 处理计时器和承诺作业按创建顺序处理的队列,没有优先级:

f2,t1

log“promise2”,添加t2

t1,t2

log“setTimeout1”,添加f1

t2,f1

log“setTimeout2”

F1

log“promise1”

因此,具有相同的优先级,日志是针对Node报告的“promise2”,“setTImeout1”,“setTimeout2”,“promise1”。

<小时/> 的 TLDR;

浏览器优先于承诺响应作业而非计时器回调。节点与给定时器和承诺作业具有相同的优先级是一致的,但请查看文档。

veryBadIdea (tm)代码承诺体系结构依赖于给定时器回调和承诺作业队列执行的优先级。这可能因主机环境(浏览器与节点)之间以及本机Promise库和已在使用中的JavaScript承诺库之间而有所不同,或者在旧版浏览器中作为Promise的polyfill包含在内。