
js
打印顺序都是 11,10,1,4,2,5,3,6,7,8,9
process.nextTick 和 setImmediate ,这两个玩意就得好好说说了。process.nextTickprocess.nextTick 的性质和 Promise 一模一样,只不过 node 中的 process.nextTick 所在的任务队列的优先级比 Promise 所在的任务队列的优先级高!process.nextTick,就只能当老二了。process.nextTick产生的任务为 微任务Max!微任务Max 所在的队列为 微队列Max!process.nextTick 和 Promise。js
结果为 start,end,1,3,2,4,5,6,7。
js
结果为 start,end,1,3,2,4,5,6,7。
js
结果为 start,end,5,7,6,8,1,3,2,4
process.nextTick,就相当于看到了Promise的亲哥哥,行为和Promise一样,但是优先级比Promise高。setImmediatesetImmediate,虽然 setImmediate 所在的也是宏队列,但是和 setTimeout 所在的不是一个宏队列,那么既然不在一起,就得有优先级的区分,那么他两个谁是大哥?我找到了下面的资料:
timers: 执行setTimeout和setInterval的回调- pending callbacks: 执行延迟到下一个循环迭代的 I/O 回调
- idle, prepare: 仅系统内部使用
- poll: 检索新的 I/O 事件;执行与 I/O 相关的回调。事实上除了其他几个阶段处理的事情,其他几乎所有的异步都在这个阶段处理。
check: setImmediate在这里执行- close callbacks: 一些关闭的回调函数,如:socket.on('close', …)
js
2, 1
js
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | 全局代码 |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | |
定时器的计时线程 |
js
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | () => { console.log(“2”);} |
定时器的计时线程 | () => { console.log(“1”);} 等1毫秒后送入定时器宏队列 |
由于示例代码实在是太少,以至于当第二次事件循环开始时,还没有超过1毫秒,所以这时主线程去查看定时器宏队列的时候,没有发现任务,因为定时器的计时线程发现还没过1毫秒,就没把() => { console.log(“1”);} 放入定时器宏队列。那么主线程就继续往下找,发现下面setImmediate的宏队列有任务,就拿出来第一个执行,在执行过程中,定时器的计时线程发现已经到了1毫秒,随即把 () => { console.log(“1”);} 放入定时器的宏队列,姗姗来迟。| 任务 | 当前执行代码 |
|---|---|
| 主线程 | () => { console.log(“2”);} |
| 微任务 | |
| 定时器的宏队列 | () => { console.log(“1”);} |
| setImmediate的宏队列 | |
定时器的计时线程 |
执行() => { console.log(“2”);}, 此时控制台打印 2| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | () => { console.log(“1”);} |
| setImmediate的宏队列 | |
定时器的计时线程 |
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | () => { console.log(“1”);} |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | |
定时器的计时线程 |
执行() => { console.log(“1”);}, 此时控制台打印 1js
1, 2
js
2, 1
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | 全局代码 |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | |
定时器的计时线程 |
js
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | |
定时器的计时线程 | () => { setTimeout(() => { console.log("1");}); setImmediate(() => {console.log("2");}); syncFunc(1000) } 等1毫秒后送入定时器宏队列 |
定时器的计时线程 没有动作。定时器的计时线程 的1毫秒时间已经到了,线程内的待执行代码被放入到定时器的宏队列中。| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | () => { setTimeout(() => { console.log("1");}); setImmediate(() => {console.log("2");}); syncFunc(1000) } |
| setImmediate的宏队列 | |
定时器的计时线程 |
| 任务 | 当前执行代码 |
|---|---|
| 主线程 | () => { setTimeout(() => { console.log("1");}); setImmediate(() => {console.log("2");}); syncFunc(1000) } |
| 微任务 | |
| 定时器的宏队列 | |
| setImmediate的宏队列 | |
定时器的计时线程 |
定时器的计时线程,等待1毫秒后会被送入定时器的宏队列。setImmediate 是立即放入队列,那么 () => {console.log("2"); 被立即放入到 setImmediate 的宏队列。定时器的计时线程 发现已经到了1毫秒,随即把 () => { console.log(“1”);} 放入定时器的宏队列| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | () => { console.log("1");} |
| setImmediate的宏队列 | () => {console.log("2");} |
定时器的计时线程 |
因为如果结束了,那么会开启第四次eventloop,回到顶部继续从微任务开始向下找,然后到定时器的宏队列,那么一定会先打印1,而不是先打印2了。| 任务 | 当前执行代码 |
|---|---|
| 主线程 | () => {console.log("2");} |
| 微任务 | |
| 定时器的宏队列 | () => { console.log("1");} |
| setImmediate的宏队列 | |
定时器的计时线程 |
执行() => { console.log(“2”);}, 此时控制台打印 2| 任务 | 当前执行代码 |
|---|---|
| 主线程 | |
| 微任务 | |
| 定时器的宏队列 | () => { console.log("1");} |
| setImmediate的宏队列 | |
定时器的计时线程 |
执行() => { console.log("1");}, 此时控制台打印 1setImmediate的宏队列 在 定时器的宏队列 的后面,定时器的宏队列 执行完后产生了一个新的 setImmediate的宏队列 的任务,当 定时器的宏队列 执行完后,还要继续 setImmediate的宏队列 的执行,所以2就在1的前面打印了。js