面试复习题-Node.js

204 阅读3分钟

✊不积跬步,无以至千里;不积小流,无以成江海

EventLoop 是什么?

Node.js 将各种函数(也叫任务或回调【即通过nodejs向操作系统发出各种请求,由操作系统给出回应】)分成至少 6 类,按先后顺序调用,因此将时间分为六个阶段:

  1. timers 阶段(setTimeout)

  2. I/O callbacks 该阶段不用管

  3. idle, prepare 该阶段不用管

  4. poll 轮询阶段【类似于问操作系统我的请求到了没】,停留时间最长,可以随时离开。

    a. 主要用来处理 I/O 事件,该阶段中 Node 会不停询问操作系统有没有文件数据、网络数据等

    b. 如果 Node 发现有 timer 快到时间了或者有 setImmediate 任务,就会主动离开 poll 阶段

  5. check 阶段,主要处理 setImmediate 任务

  6. close callback 该阶段不用管

Node.js 会不停的从 1 到 6 循环处理各种事件,这个过程叫做事件循环(EventLoop)

javascript是单线程,所以只有唯一的事件循环,这个时候js就把所有任务分为了两种:同步任务和异步任务。
而异步任务的两种分类分别为:宏任务和微任务。事件的执行顺序是先执行微任务,然后执行宏任务。微任务按先进先出的顺序执行;微任务清空后再执行宏任务,按先进先出的顺序取出执行。

nextTick

process.nextTick(fn) 的 fn 会在什么时候执行呢?

在 Node.js 11 之前,会在每个阶段的末尾集中执行(俗称队尾执行)。

在 Node.js 11 之后,会在每个阶段的任务间隙执行(俗称插队执行)。

浏览器跟 Node.js 11 之后的情况类似。可以用 window.queueMicrotask 模拟nextTick。

Promise

Promise.resolve(1).then(fn) 的 fn 会在什么时候执行?

这要看 Promise 源码是如何实现的,一般都是用 process.nextTick(fn) 实现的,所以直接参考 nextTick。

async / await

这是 Promise 的语法糖,所以直接转为 Promise 写法即可。

总结

async/await参考了promise,promise参考了nextTick,nextTick参考了queueMicrotask。所以其实本质都是一个东西

例子

截屏2024-03-10 15.47.02.png

其实结果是D。因为存在谁先启动不确定的情况,所以有可能nodejs停留在poll阶段的时候反而才开始setTImeOut,这种情况就会先执行SetImmediate,导致先setIm再setT。剩下就是按顺序执行了。

截屏2024-03-10 15.47.21.png

await async2()
    console.log('2')
}

被改写为了

async2().then(()=>{console.log('2')})

帮助判断
  1. 首先async函数都先放到后面去看。
  2. 第一个执行的就是cl 4
  3. 之后再setTimeout任务中写入5
  4. 之后执行async1
  5. 进入async1后 cl 1
  6. 由于await cl 2,所以把cl 2 放到nextTick里面
  7. 再直接到async2
  8. 进入async2后 cl 3
  9. 这里async1执行完了,回到new promise,由于new promise里面的函数是立刻执行的
  10. 所以进入new promise后cl 6
  11. 由于有.then所以把cl 7也放入到nextTick里面
  12. 之后执行cl 8
  13. 然后由于是node11之后的,存在插队机制,所以先执行插队内容,即nextTick的内容
  14. 再最后执行setTimeout的内容

所以结果为 41368275