JS 执行顺序问题、Promise 运作顺序问题

function f() {
  console.log("A");
  setTimeout(() => console.log("F"))
  new Promise((resolve, reject) => {
    console.log("B");
    resolve();
    console.log("C");
  }).then(() => console.log("E"));
  console.log("D");
}
f();

输出结果为:

A
B
C
D
E
F

setTimeout 那一块比较好理解,其实就是Event Loop,但是 Promise 不是很了解,有没有大佬能解释一下,Promise 内部究竟是如何运作的?为什么是先E再F?

阅读 2.1k
1 个回答

PromisesetTimeout进的是不同的队列,假设Promise进的队列 A,setTimeout进的队列 B, A 的优先级要大于 B, 只有 A 执行完之后才会执行 B, 当 new Promise 执行完之后,因为后面跟着then,会把后面的then的回调推入 A ,然后执行刚刚推入 A 的回调,等执行完了,最后执行 B 里面的setTimeout

你可以看看后面的这个文章,里面的演示很形象
Tasks, microtasks, queues and schedules

补充

上面的队列 A 就是microtask, 队列 B 就是macrotask. 他们都属于异步任务, 区别是 microtask 优先于macrotask,并且每次时间循环中, macrotask 只会提取一个执行, 而microtask会一直提取,知道microtask队列清空.如果then "E"后面还跟着then,那么还是会执行后面的then,最后才会执行到setTimeout
更详细的内容可以查看下面的这篇文章
理解 JavaScript 中的 macrotask 和 microtask

再次补充

之后在测试的时候发现一个问题,下面的代码在nodechrome执行结果不一致.

setTimeout(() => {
  console.log('settimeout1')
}, 0)
setTimeout(() => {
  Promise.resolve().then(() => {
    console.log('promise')
  })
}, 0)
setTimeout(() => {
  console.log('settimeout2')
}, 0)
// 在chrome下的输入
// settimeout1
// promise1
// settimeout2

// 在node下执行的输出,大多数时候输出下面的顺序,偶尔会输出跟chrome一致的结构
// settimeout1
// settimeout2
// promise1

如果按照每次macrotask只拉取一个任务执行的话,那node的输出是什么鬼.
抱着这个疑问,继续翻文章
原因是因为chromenode的关于Event-Loop的实现不同
详细的解释可以看知乎的这个回答 Promise在node和chrome下表现为什么会有差异?

参考

  1. Tasks, microtasks, queues and schedules
  2. 理解 JavaScript 中的 macrotask 和 microtask
  3. Javascript 基础夯实——理解 Event Loop、Micro Task & Macro Task
  4. Promise的队列与setTimeout的队列的有何关联?
  5. 从event loop规范探究javaScript异步及浏览器更新渲染时机
  6. [Node] Macrotask和Microtask Queue在Node端的不同表现
  7. Microtasks & Macrotasks — More On The Event Loop
  8. Promise在node和chrome下表现为什么会有差异?
  9. JavaScript 运行机制详解:再谈Event Loop
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题