event loop它的执行顺序:

  • 一开始整个脚本作为一个宏任务执行
  • 执行过程中同步代码直接执行,宏任务进入宏任务队列,微任务进入微任务队列
  • 当前宏任务执行完出队,检查微任务列表,有则依次执行,直到全部执行完
  • 执行浏览器UI线程的渲染工作
  • 检查是否有Web Worker任务,有则执行
  • 执行完本轮的宏任务,回到2,依此循环,直到宏任务和微任务队列都为空

微任务包括:MutationObserver、Promise.then()或reject()、Promise为基础开发的其它技术,比如fetch API、V8的垃圾回收过程、Node独有的process.nextTick。

宏任务包括:script、script 、setTimeout、setInterval 、setImmediate 、I/O 、UI rendering

# 1 Promise的几道基础题

# 1.1 题目一

⚡ 30 秒速记

  • new Promise 的 executor 会在构造时同步执行,所以先输出 promise1
  • 没有调用 resolve 或 reject,Promise 会一直保持 pending
  • 构造器之后的普通 console.log 仍按同步顺序执行

这段代码会先输出 promise1,再输出 1 和一个状态为 pending 的 Promise。 原因是 new Promise 的 executor 在构造实例时会同步执行,并不会等到微任务阶段。executor 内没有调用 resolve 或 reject,所以实例始终保持 pending。构造完成后,外层的 console.log 继续按同步代码的顺序执行。

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
})
console.log('1', promise1);
  • 从上至下,先遇到new Promise,执行该构造函数中的代码promise1
  • 然后执行同步代码1,此时promise1没有被resolve或者reject,因此状态还是pending
'promise1'
'1' Promise{<pending>}

# 1.2 题目二

⚡ 30 秒速记

  • 从上至下,先遇到new Promise,执行其中的同步代码1
  • 再遇到resolve('success'), 将promise的状态改为了resolved并且将值保存下来
  • 跳出promise,往下执行,碰到promise.then这个微任务,将其加入微任务队列
  • 本轮宏任务全部执行完毕,检查微任务队列,发现promise.then这个微任务且状态为resolved,执行它

最终输出顺序是 1 2 4 3。 创建 Promise 时,executor 会立即同步执行,所以先打印 1;调用 resolve('success') 后状态变为 resolved,但后面的同步代码仍会继续执行并打印 2。随后 then 回调进入微任务队列,主流程先打印 4。等本轮同步代码执行完,事件循环才处理这个微任务并打印 3。

webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
折叠侧边栏
收起全部