JS macrotask 与 microtask
首先看下面这段代码:
1 | console.log(0) |
按照直观映像, setTimeout的延时为0, console应该立即执行, 应该输出的是 0 1 2 3 然后运行代码后我们发现输出的结果为 0 3 2 1, 这是为什么呢? (因为setTimeout最小执行时间为4ms啊, 笑)
我们知道javascript是单线程的, 但是由于异步的存在, 可以”在同一时间做两件事情”;这是由于js存在两种task,一种为macrotask,比如:整体js代码,setTimeout,setInterval,setImmediate, I/O以及ui render,还有一种为microtask,比如process.nextTick,浏览器的原生Promise,Object.observe,MutationObserver。每次macrotask的代码执行后都会检查microtask内有没有代码,如果有,则取出所有的任务进行执行。
所以当浏览器执行js代码时也就创建了一个macrotask,macrotask可以有多个但是microtask只能有一个,所以以上代码经历的过程为:
- 浏览器执行一个macrotask(整体js代码)
- 检查microtask(每次macrotask执行完都会检查,后面过程就不再添加这个动作了,默认有)
- 执行
console.log(0)
- 创造一个新的macrotask,为
console.log(1)
,挂起 - 创造了一个microtask,
Promise.resolve(2).then(val => console.log(val))
,挂起 - 执行
console.log(3)
,console出了3 - 检查microtask,有microtask的话将其中所有的任务全部取出进行执行,这里只有一个
- 执行
console.log(2)
; - 整体js代码的这个macrotask任务全部执行完成
- 执行下一个macrotask,就是setTimeout所在的这个,即执行了console.log(3)
- 此时没有任何任务队列, 代码执行完毕