Appearance
异步和事件循环机制
浏览器与Node的事件循环(Event Loop)有何区别一张图带你搞懂Node事件循环
- Node.js采用非阻塞I/O模型,这意味着当进行I/O操作(如文件读写、网络请求等)时,Node.js不会等待操作完成后再执行下一行代码,而是会继续执行后续的代码。
- 在进行异步操作时,Node.js会注册回调函数,并继续执行其他任务。当异步操作完成后,Node.js会将回调函数添加到事件队列中,等待事件循环机制的处理
事件循环
事件循环的执行过程分为几个阶段,每当进入某一个阶段的时候,都会从对应的回调队列中取出函数去执行。当队列为空或者执行的回调函数数量到达系统设定的阈值,就会进入下一阶段。
- timers, 处理已经到期的定时器回调函数。
- pending callbacks, 处理系统级回调函数。
- idle, prepare, 用于node内部操作。
- poll, 检索新的I/O事件并执行对应的回调函数。如果没有待处理的I/O事件,事件循环会等待新的事件到达。node 将在适当时机在此处暂停。
- check, 执行 setImmediate() 的回调。
- close callbacks, 一些关闭的回调函数,如:socket.on('close', ...)。
详细介绍timers、poll、check
这3个阶段,因为日常开发中的绝大部分异步任务都是在这3个阶段处理的。
timers
timers 阶段会执行 setTimeout 和 setInterval 回调,并且是由 poll 阶段控制的。 同样,在 Node 中定时器指定的时间也不是准确时间,只能是尽快执行。
poll
如果poll中有回调函数需要执行,依次执行回调,直到清空队列。
如果poll中没有回调函数需要执行,已经是空队列了。则会在这里等待,等待其他队列中出现回调,
如果其他队列中出现回调,则从poll向下到over,结束该阶段,进入下一阶段。
如果其他队列也都没有回调,则持续在poll队列等待,直到任何一个队列出现回调后再进行工作。
check
setImmediate()的回调会被加入check队列中,从event loop的阶段图可以知道,check阶段的执行顺序在poll阶段之后。
个人理解
代码块执行 ->遇到异步任务 ->将异步任务放入到对应的异步事件处理函数中执行,同时执行栈继续往下执行 ->代码块代码执行完毕,判断是否需要进行事件循环 ->发现存在异步任务,进入事件循环 ->进入阶段前,查看nextTick队列和微任务队列是否存在任务,如有按顺序执行 ->timers阶段,按顺序执行已经处理完的定时器回调函数 ->每执行一个任务,都会重新查看nextTick队列和微任务队列是否存在任务,如有按顺序执行
->pool阶段 ->check阶段