-
node是单线程的,但是它可以和内核对话,大多数内核是多线程的,node会尽量将操作装载到内核,让内核可以同时执行多个操作,当有一个操作执行完后,它就会告诉Node,node把回调加入轮询队列,最终执行。
-
node为了与内核对话专门用了一个库:libuv。它负责时间回到主线程之后,回调执行的事时间回到函数会排队执行。
-
同步任务早于异步任务执行
-
node的事件循环有本轮循环和次轮循环(仅针对异步事件)
本轮循环:同步任务 => process.nextTick() => 微任务
- Node 规定,process.nextTick 和 Promise 的回调函数,追加在本轮循环,即同步任务一旦执行完成,就开始执行它们。setTimeout、setInterval、setImmediate 的回调函数,追加在次轮循环。
其中process.nextTick()是异步任务里最早执行的(不论它在什么位置,都会在异步任务中最先处理) - 语言规定,Promise 对象的回调函数,会进入异步任务里面的”微任务”(microtask)队列。微任务队列追加在 process.nextTick 队列的后面,也属于本轮循环。
事件循环机制
node只有一个主线程,事件循环机制会在主线程上执行,事件循环开始执行之前会进行事件循环初始化,即执行同步事件、发送异步请求、规定定时器生效时间、执行process.nextTip()。在这之后进行事件循环,直到异步回调队列执行完。
只有一个阶段的回调函数队列清空了,该执行的回调函数都执行了,事件循环才会进入下一个阶段。
1、timers //处理setTimeout()和setInterval()的回调函数
2、I/O callbacks //操作回调函数(除了那两个定时器)
3、idle, prepare //供 libuv 内部调用
4、poll //轮询时间,用于等待还未返回的 I/O 事件,比如服务器的回应、用户移动鼠标等等
5、check //执行 setImmediate() 的回调函数
6、close callbacks //阶段执行关闭请求的回调函数,比如 socket.on(‘close’, …)