• nodejs事件循环


    简介

    单线程

    提到node,我们就可以立刻想到单线程、异步IO、事件驱动等字眼。首先要明确的是node真的是单线程的吗,如果是单线程的,那么异步IO,以及定时事件(setTimeout、setInterval等)又是在哪里被执行的。
    其实,按照严格来说,node并不是单线程的。node中存在着多种线程,包括:

    js引擎执行的线程

    定时器线程(setTimeout, setInterval) : 倒计时结束后(异步)会把回调 放在事件队列里面

    异步http线程(ajax)

    node中的单线程是指js引擎只在唯一的主线程上运行

    事件循环概述

    主线程将所有任务都放在循环队列中,
    然后由底层的libuv库从循环事件队列中取出任务分配给不同的线程去处理,
    主线程同时也会进行回调处理,整个过程形成事件循环

    nodejs实现异步机制的核心便是libuv,libuv承担着nodejs与文件、网络等异步任务的沟通桥梁

    通过事件驱动模型实现了高并发和异步 I/O ,适合处理I/O密集型任务

    六个阶段

    node的事件循环共有六个阶段,在一次事件循环中这六个阶段按顺序会一直循环执行,直至事件处理完成。
    在这里插入图片描述
    每一个阶段有一个队列,event loop执行到该阶段时,会该阶段的队列里的所有callback,当队列callback为空时,或callback执行到上限的时,就跳至下一阶段进行执行。

    各阶段描述

    timers 阶段: 这个阶段执行timer(setTimeout、setInterval)的回调,该阶段新创建的setTimeout、setInterval 会继续放在下一个轮回循环阶段执行

    pendding callbacks 阶段: 执行一些系统操作的回调(比如网络通信的错误回调);

    idle, prepare 阶段: 仅node内部使用;

    poll 阶段: 获取新的I/O事件, 适当的条件下node将阻塞在这里(比如:文件读取操作,http请求 回调 )
    底层代码在poll阶段执行的时候,会传入一个timeout超时时间,timeout超时时间到了,则退出poll阶段,执行下一个阶段。

    check 阶段: 执行setImmediate() 设定的callbacks;

    close callbacks 阶段: 比如socket.on(‘close’, callback)的callback会在这个阶段执行。

    事件循环执行过程

    • 执行前,会先执行同步任务、在执行process.nextTick 、微任务 ,在进入timers阶段

    • 在事件循环的每一个子阶段退出之前都会执行:process.nextTick(先执行于microtaks) microtaks.如果有的话

    • node 的初始化
      初始化 node 环境。
      执行输入代码
      执行 process.nextTick 回调。
      执行 microtasks。

    • 进入 event-loop

    • 进入 timers 阶段

    • 进入IO callbacks阶段。

    • 进入 idle,prepare 阶段:

    • 进入 poll 阶段
      在这里插入图片描述

    • 进入 check 阶段。

    • 进入 closing 阶段。

    • 检查是否有活跃的 handles(定时器、IO等事件句柄)。
      如果有,继续下一轮循环。
      如果没有,结束事件循环,退出程序。

    例子

    const fs = require('fs');
    setTimeout(() => {
      // 新的事件循环的起点
      console.log('1');
    });//没填默认为1,主线程执行时间大于1ms,所以在timer阶段先执行。如果设置为2ms的话,则会先执行setImmediate
    
    // 异步io,读取需要时间,当setTimeout时间较短的时候,setTimeout会比它先
    fs.readFile('./text.txt', { encoding: 'utf-8' }, (err, data) => {
      if (err) throw err;
      console.log('3');
    });
    setImmediate(() => {
      console.log('2');
    });
    // 1 2 3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    震惊,一行MD5居然让小伙伴都回不了家!!!
    动态库静态库对比
    JavaEE——Servlet上传文件
    增材制造中如何使用HOOPS进行3D模型轻量化处理?
    每年大促都要补习JVM调优,今年我都总结到这里了。
    继承、封装和多态
    C/S架构学习之基于UDP的本地通信(服务器)
    思科、华为、华三、锐捷网络设备巡检命令
    C语言重点突破(四)自定义类型详解
    FCOS网络详解
  • 原文地址:https://blog.csdn.net/weixin_44730897/article/details/128135836