010Node事件循环

参考
    1. 【译】Node.js 事件循环、定时器、process.nextTick()
        知乎
            https://zhuanlan.zhihu.com/p/461073533
        官网
            https://nodejs.org/zh-cn/docs/guides/event-loop-timers-and-nexttick/
 

[A] node事件循环的六个阶段

    timers阶段:

        执行定时器回调(setTimeout, setInterval)

    I/O callback阶段:

        处理I/O相关的回调(文件读写,数据库操作,网络请求, ...)

    idle, prepare阶段:

        近在node内部使用的阶段

    poll阶段:

        空转/循环阶段,其内部有任务,则会同步执行

    checks阶段:

        执行setImmediate的回调

    close callback阶段:

        执行相关事件回调的关闭操作


   

[B] node中的代码执行机制

    1. 主代码从上往下顺序执行,遇到的异步代码,根据其类型放入对应的队列中等待执行

        setTimeout, setInterval     ->      timers队列

        I/O                         ->      I/O队列

        setImmediate                ->      check队列

        ...

 

        注:

            1. 上述,遇到的异步代码,会被首先放在异步模块中,等待其达到回调的条件(定时器到期,网络请求成功响应, ...)

            2. 达到条件的回调,才会被放入到事件循环对应的队列中去

            3. 例外情况,setImmediate会直接被放入到check队列队列中去(没有先放入异步模块的过程)

 

    2.主代码执行结束,开始进入事件轮询(循环)

        进入事件轮训之前,先执行微任务队列:

              process.nextTicK队列中的任务

              微任务队列中的任务

        随后,进入事件循环

          从上往下,依次经历:

              timer阶段

              poll阶段

              check阶段

 

    3. 执行过程:

        1. 在timer阶段中,若timer队列中有已到期的回调,则按顺序执行所有的回调,

            然后向下进入poll阶段

        2. 在poll阶段,若poll中存在待执行的I/O回调,则会同步执行所有回调

            然后,检查check队列是否有待执行的回调,若有,则进入check阶段

        3. 在check阶段,按顺序执行check队列中的所有回调,然后回到poll阶段

 

        poll阶段:

            1. poll阶段实际是一个空转等待的过程

                此时,是因为整体代码并未完全执行完毕(主代码执行结束,但异步代码还会达到回调条件)

            2. poll阶段,

                poll阶段两种理解:

                    理解1:

                        poll阶段会持续去判断timer队列和check队列中是否存在可执行的任务

                        若有,则按照顺序执行check队列,再执行timers队列中的所有任务

                        然后,再回到poll阶段继续等待

                    理解2:

                        事件轮训阶段,就一直在timers,poll,checks三个阶段按顺序反复循环,若如到对应阶段的队列中存在待执行任务,则去执行(清空该队列)

                两种理解均可,逻辑是一样的

 

            3. poll阶段的结束条件:

                1. 异步模块中,不存在尚在等待满足条件的回调,且事件循环各阶段对应的队列均为空,则结束事件循环。

                    注:这是代码执行结束时的正常停止逻辑

                2. poll阶段等待的时间达到硬件规定的最长时间,如:网络请求时间太长

                    注:这属于强制停止,是一种异常情况,这是不希望看到的

 

    4. 微任务队列

        1. 在事件循环中,从timer -> poll -> check 为一次完整的轮询

        2. 而事件轮询就是上述轮询重复的过程

        3. 而实际上,事件轮询的队列全部为宏任务队列,在轮询中,还涉及到一个微任务队列

        4. 代码执行过程中,遇到的微任务,如promise.then等会儿比放入到微任务队列,等待执行

        5. 每次事件轮询之前,都会去清空微任务队列,然后才开始下一轮的事件轮询

    5. nextTick

        1. nextTick是node中独有的一种异步回调方式

        2. nextTick的回调会被专门放在nextTick队列中去

        3. nextTick的执行优先级高于微任务队列

            因此,每次事件轮询前会,先清空nextTick队列,再清空微任务队列,然后在进入下一轮事件轮询

 

 

 

 

 

posted @ 2022-07-15 16:46  CarreyB  阅读(32)  评论(0编辑  收藏  举报