zoukankan      html  css  js  c++  java
  • 初探nodejs事件循环机制event loop

    nodejs的特点

    nodejs 具有事件驱动和非阻塞I/O的特点。

    事件驱动是指nodejs把每一个任务当成事件来处理。

    非阻塞I/O是nodejs遇到I/O任务时,会从线程池调度单独的线程处理I/O操作,不会阻塞主线程。

    事件循环原理

    Node.js 在主线程里维护了一个事件队列,当接到请求后,就将该请求作为一个事件放入这个队列中,然后继续接收其他请求。

    当主线程空闲时(没有请求接入时),就开始循环事件队列,检查队列中是否有要处理的事件,这时要分两种情况:

      如果是非 I/O 任务,就亲自处理,并通过回调函数返回到上层调用;

      如果是 I/O 任务,就从 线程池 中拿出一个线程来处理这个事件,并指定回调函数,然后继续循环队列中的其他事件。

    当线程中的 I/O 任务完成以后,就执行指定的回调函数,并把这个完成的事件放到事件队列的尾部,等待事件循环,当主线程再次循环到该事件时,就直接处理并返回给上层调用。

    流程图

    每次循环的六个阶段

      timers阶段:这个阶段执行定时器队列中的回调,如 setTimeout() 和 setInterval()

      I/O callbacks: 这个阶段执行几乎所有的回调。但是不包括close事件,定时器和setImmediate()的回调。

      idle, prepare: 这个阶段仅在内部使用,可以不必理会。

      poll: 等待新的I/O事件,node在一些特殊情况下会阻塞在这里。

      check: setImmediate()的回调会在这个阶段执行。

      close callbacks: 例如socket.on('close', ...)这种close事件的回调。

    下面我们来按照代码第一次进入libuv引擎后的顺序来详细解说这些阶段:

      当个v8引擎将js代码解析后传入libuv引擎后,循环首先进入poll阶段。

      poll阶段的执行逻辑如下:

        先查看poll queue中是否有事件,有事件就按先进先出的顺序依次执行回调。

        当queue为空时,会检查是否有setImmediate()的callback,如果有就进入check阶段执行这些callback。

        当queue为空时,同时也会检查是否有到期的timer,如果有,就把这些到期的timer的callback按照调用顺序放到timer queue中,之后循环会进入timer阶段执行queue中的 callback。

        这两者的顺序是不固定的,收到代码运行的环境的影响。

        如果两者的queue都是空的,那么loop会在poll阶段停留,直到有一个i/o事件返回,循环会进入i/o callback阶段并立即执行这个事件的callback。

        值得注意的是,poll阶段在执行poll queue中的回调时实际上不会无限的执行下去。

        有两种情况poll阶段会终止执行poll queue中的下一个回调:1.所有回调执行完毕。2.执行数超过了node的限制。

    特别感谢:

    https://www.cnblogs.com/onepixel/p/7143769.html

     

  • 相关阅读:
    对成本的理解
    Oracle ERP中帐户类型和会计科目分类的关系---待完善
    固定资产调整对资产折旧的影响
    20201111 eset internet security keys | NOD 32 keys | ESET MOBILE LICENSE KEYS
    一些常用到的windows ISO download 文件下载资源
    读《改变心理学的40项研究》有感,之一
    有归从,可与有。2019.07.09.
    灼钓鱼炭 2019.07.08.
    人居一世间, 忽若风吹尘 2019.07.07.
    exported wechat's voice! 成功导出微信语音! 2019.07.06.
  • 原文地址:https://www.cnblogs.com/zifayin/p/11419808.html
Copyright © 2011-2022 走看看