在学习Node的过程中,难免对事件循环机制有深刻的理解,其中Macrotask(大任务)和Microtask(小任务)任务)更多的人感到困惑。google了一下,找到了几个资料,比较能说明它们的原理。所以这里是总结+处理。一句话解释,在Nodejs的事件循环机制中,任务有两种队列:Macrotask队列和Microtask队列。在事件循环中,这两个队列会分两步执行。第一步会固定执行一个(且只执行一个)Macrotask任务,第二步会执行整个Microtask队列中的所有任务。而且,在执行Microtask队列任务时,也允许加入新的Microtask任务,直到所有Microtask任务执行完毕,循环才会结束。宏任务一般包括:setTimeout、setInterval、setImmediate、I/O、UI渲染;Microtasks一般包括:process.nextTick、Promises、Object.observe、MutationObserver。事件循环机制详解从一个事件循环开始,到最后会经过以下步骤:查看Macrotask队列,选择最早加入的任务X(也就是最早的),并设置它作为“当前正在运行的任务”。如果任务X不存在,直接跳到第4步,运行任务X,即运行对应的回调函数。将“当前运行的任务”设置为null以从Macrotask队列中删除任务X。查看Microtask队列:1)选择最老的任务a,如果任务a不存在,直接结束Microtask队列。2)将任务a设置为“当前正在运行的任务”并执行。3)将“当前运行的任务”置为null,将任务a从Microtask队列中移除。4)选择下一个最早的任务b,跳到步骤2)。5)结束队列,直到队列中没有剩余任务。跳回到第1步并检查下一个Macrotask任务。关于eventloop的步骤,参考文档里面的《理解 Node.js 事件循环》一文说的很好,很详细。强烈建议想了解的同学一定要看。如何选择Macrotask或Microtask?可以这么简单的理解:如果你想让一个任务立即执行,那就设置成Microtask,否则还是用Macrotask比较好。因为可以看出Node虽然是异步非阻塞的,但是在一个事件循环中,Microtask的执行方式基本是同步的。可能出现的问题相信大家看完后已经意识到,如果一个Microtask队列过长,或者在执行过程中不断加入新的Microtask任务,下一个Macrotask任务会很长时间不会执行。因此,您可能会遇到UI未刷新或I/O任务未完成的情况。应该考虑到这一点,至少Microtask任务中的process.nextTick任务设置了(在事件循环中)最大调用次数,称为process.maxTickDepth。默认为1000。一定程度上避免了上述情况。参考资料了解Node.js事件循环事件循环上下文中微任务和宏任务的区别
