检验你是否掌握process.nextTick()和setImmediate()

178 阅读2分钟

前言

今天在看《深入浅出Node.js》时,清楚了process.nextTick()和setImmediate()的细微区别。在这里用一道代码题,来加深印象。

代码题

直接看题看题👀

setImmediate(function() {
  console.log('immediate1');
  setImmediate(function() {
    console.log('immediate2');
  })
  process.nextTick(function() {
    console.log(`process1`);
  })
})

process.nextTick(function() {
  console.log(`process2`)
  setImmediate(function() {
    console.log('immediate3');
    process.nextTick(function() {
      console.log(`process3`);
    })
  })
})

process.nextTick(function() {
  console.log(`process4`)
  setImmediate(function() {
    console.log('immediate4');
    process.nextTick(function() {
      console.log(`process5`);
    })
  })
})

setImmediate(function() {
  console.log('immediate5');
  process.nextTick(function() {
    console.log(`process6`);
  })
})

console.log(`window`)

请说明输出顺序

答案是

window
process2
process4
immediate1
process1
immediate5
process6
immediate3
process3
immediate4
process5
immediate2

基础知识

你做对了吗?不管你是否做对都不要担心?会的和我复习一遍,不会的学会就可以啦!

如果你想做对这道题,必然要了解process.nextTick()setImmediate()的执行顺序

process.nextTick()setImmediate()的目的都是为了立即异步执行一个任务

process.nextTick()中的回调函数执行优先级要高于setImmediate()

因为在事件循环对观察者的检查是有先后顺序的,process.nextTick()属于idle观察者setImmediate()属于check观察者在每一个轮循环检查中,idle观察者先于I/O观察者,先于check观察者。

在行为上,process.nextTick()在每轮循环中会将数组中的回调函数全部执行完,而setImmediate()在每轮循环中执行链表中的一个回调函数。

当第一个setImmediate()的回调函数执行后,并没有立即执行第二个,而是进入了下一轮循环,再次按process.nextTick()优先、setImmediate次后的顺序执行。之所以这样设计,是为了保证每轮循环能够较快地执行结束,防止CPU占用过多而阻塞后续I/O调用的情况

程序执行顺序

知道这些之后我们回到这道题上,因为process.nextTick()的执行优先级要高于setImmediate()setImmediate()每次循环只能执行一次。

运行程序后,在第一轮事件循环中,先输出window,然后执行process.nextTick()进入下一次事件循环,因为process.nextTick()是将回调函数保存在一个数组中,我们在这次循环中调用了两次process.nextTick(),他两个的回调函数按照词法作用域的顺序存储到数组中,所以输出的顺序为 process2process4

在本次循环中可以执行一次setImmediate()方法,也按照词法作用域的顺序执行,所以先执行第一个setImmediate(),输出为immediate1,在回调函数中有一个setImmediate()process.nextTick(),先执行process.nextTick()方法,输出process1,进入第二轮循环,再执行之前的setImmediate(),输出immediate5,因为回调函数中有process.nextTick(),继续输出process6,进入第三轮循环

此时我们发现第一层的process.nextTick()setImmediate()都已经执行完了,然后执行其回调函数内部的setImmediate()方法,先执行process.nextTick()中的,再执行setImmediate()。这就是程序的执行顺序。

结尾

如果你理解的逻辑和我不同,欢迎在评论区回复哦!我也学习学习😁

可以用您发财的小手给我一个宝贵的赞吗?🤩