nextTick 和 microTask 发生在逐阶段移动的tick上。
这意味着如果tick不发生,nextTick或microTask就不会发生。
那么如果Timer、Pending等没有Callback,Polling就处于等待状态,nextTick不会永远发生,对吗?
如果在某些代码上打勾,则表明架构存在问题,例如内部无限循环,或消耗大量 CPU 的操作,或阻塞操作,例如同步读取大文件。 JS没有等待操作,或者暂停逻辑。您可以使用here中的下一个图表来理解这一点:
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
事件循环的每个阶段意味着node.js(实际上是libuv)只是一个查找,某个计时器是否已过期?,是否满足待处理回调的某些条件?等等,并且每个阶段的检查都是非阻塞的,这与一些 havy 或阻塞逻辑,可以在该检查的结果中启动
如果发生一些卡住的情况,我推荐以下解决方案:
对于无限循环,请尝试重构代码以避免它们,因为事实上,您的代码已经在无限事件循环中工作了,因此,使用 nextTick 或 setImmediate 来摆脱阻塞代码风格
对于阻塞操作(使用网络、文件系统、数据库等),将逻辑重构为异步代码风格
对于消耗大量 CPU 的操作,请使用 child_process 并将大量逻辑移动到单独的线程中