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。