在node和浏览器中,JS事件循环(EventLoop)今天群里讨论了一个话题,执行console.log(1)setTimeout(()=>{console.log(2)})Promise.resolve().then(()=>{console.log(3)}).then(()=>{console.log(4)})console结果.log(5)的是,在15342之前,我只了解了JS事件循环的大概思路。今天想深入了解一下,查了些资料,整理一下思路。为什么JS会有事件循环,因为Javascript是单线程运行的。为什么一定要单线程?因为在JavaScript诞生之初,就是在浏览器中运行和操作DOM。如果是多线程,两个线程同时操作一个DOM,那么浏览器会很纠结,不知道该听谁的。单线程有个问题,就是顺序执行。当遇到耗时任务时,它会一直等待,效率低下。于是有了事件循环,将异步任务添加到一个事件队列中,主进程继续执行下面的代码,等待异步任务处理完成后,会通知主进程执行异步任务的回调,大大提高了效率。如果部署得好,JavaScript程序是不会被阻塞的,这也是为什么NodeJS平台可以用极少的资源来应对大流量访问的原因。浏览器中的事件循环我们都知道浏览器是多进程的(一个进程可以有多个线程,JavaScript是单线程的),其中一个进程我们前端工程师非常熟悉,就是渲染进程,也叫浏览器内核。渲染进程包括几个进程,比如下面的GUI渲染线程(负责解析HTMLCSS并渲染成页面)JS引擎线程(负责执行JS代码,也就是我们常说的V8引擎)事件触发线程(也就是我理解的触发事件队列,一些异步操作(setInternal、setTimeout、异步请求等)完成后的回调就放在这里,等待JS引擎线程执行完代码才开始执行回调函数里面)定时触发线程(对于setInternal和setTimeout的定时,时间到的时候会把自己的回调放到事件队列中,空闲的时候等待JS主进程执行代码)异步http请求线程(也就是我们常说的异步请求,完成后,也会把它回调到事件队列中)为什么上面的代码会输出15342?从逻辑上讲,setTimeout函数是异步的,它会被放入事件队列中。继续执行下面的代码,应该是13452,再说说在JS里面,还有一个叫microtask的东西。这个小东西是在主任务执行完之后,事件队列中的回调函数之前执行的。Promise属于microtask。也就是说主任务开始执行,遇到异步任务就放入事件队列,主任务继续执行。maintask执行完后,立即执行microtask,然后执行事件队列中的回调函数。NodeJS中的事件循环node中的事件循环与浏览器不同,看下面的代码,输出的是什么setTimeout(()=>console.log(1))setImmediate(()=>console.log(2))process.nextTick(()=>console.log(3))Promise.resolve().then(()=>console.log(4));(()=>console.log(5))()节点官网上有EventLoop的介绍。在这张图中,节点中的事件循环包括六个阶段。主任务执行完毕后,会依次进入这六个阶段。timers(处理setTimeout和setInterval的回调函数,主线程会检查当前Time,是否满足timer的条件,如果满足,则执行回调函数,否则,离开该阶段。)I/Ocallbacks(执行一些错误的回调和poll应该执行但上轮没有执行的回调)idleprepare(这个阶段只针对libuv内部调用,我们可以先忽略它)poll(等待I/还没有返回事件的O,执行回调,等待过程中如果有定时器计时,则进入定时器阶段,如果有setImmediate,直接进入check阶段)check(setImmediate(的回调函数))是在这个阶段执行的)closecallbacks(这个阶段执行关闭请求的回调函数,比如socket.on('close',...))以上代码setTimeout放入事件循环队列(虽然没有设置延迟时间,但是是异步函数,还是需要放入事件循环队列中),然后setImmediate也放入事件循环队列中,然后是process.nextTick(先于执行)promise,主任务执行完后会立即执行),然后是Promise(不用说,但是会在process.nextTick之后执行,优先级没有process.nextTick高),后面是同步函数立即执行,打印5,然后执行process.nextTick,打印3,再执行Promise,打印4。然后进入事件循环,首先进入timers阶段,检查发现时间到了,执行回调,打印1,然后执行后面的阶段,等到check阶段,执行setImmediate的回调,打印3。这只是一种情况,还有很多其他情况你可以自己尝试。这将使您对节点的事件循环机制有更深入的了解。初步理解,如有错误请指正~参考文章https://funteas.com/topic/5a64e9482630e6f31583701dhttp://www.ruanyifeng.com/blog/2018/02/node-event-loop.htmlhttp://www.ruanyifeng.com/blog/2014/10/event-loop.htmlhttps://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
