温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

nodeJs事件循环运行代码怎么写

发布时间:2023-04-15 11:20:35 来源:亿速云 阅读:107 作者:iii 栏目:开发技术

这篇文章主要讲解了“nodeJs事件循环运行代码怎么写”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodeJs事件循环运行代码怎么写”吧!

    Nodejs运行时

    JS语言是同步,阻塞,单线程的,但是nodejs不是。Nodejs由三个主要组件:

    • 外部依赖例如 v8,libuv,crypto

    • 提供文件和网络服务的c++模块

    • 基于c++模块上层封装的JS库

    nodeJs事件循环运行代码怎么写

    nodejs的异步特性主要由libuv提供。libuv是跨平台的使用c语言写的库,它主要提供对异步操作的支持。

    node运行时代码运行

    nodeJs事件循环运行代码怎么写

    当我们在Nodejs中执行JS代码时,是由v8引擎处理代码执行,v8包括一块内存区域(堆)和调用栈。当定义函数,变量时,从堆中分配内存,当执行代码时将函数入栈,函数返回时出栈。

    当执行异步操作时,libuv将接管该任务,然后使用操作系统的异步机制运行任务。如果缺乏系统级的异步机制,就使用线程池运行任务,保证主线程不被阻塞。

    Event Loop

    nodeJs事件循环运行代码怎么写

    事件循环是一个nodejs应用运行后一直存在的循环。存在着六个不同的队列,每个都存储着不同的回调。

    • Timer queue(定时器队列),最小堆,由setTimeout, setInterval创建

    • IO队列:文件、网络操作

    • check队列,任务由setImmediate产生,node专有

    • close队列, 与异步任务的close事件相关

    • nextTick队列

    • promise队列

    除了两个微任务队列,其他队列都是libuv自带的

    如何工作?

    同步代码优于异步代码,事件循环是call stack为空后开始。事件循环遵循的优先级规则:

    • 微任务队列有任务,先处理完。nextTick先于promise

    • 定时器任务执行

    • IO队列

    • check队列

    • close队列

    需要注意的是在定时器队列,IO队列,check队列,close队列执行一个任务后都会检查并运行微任务队列。

    实验

    实验1

    // index.js
    console.log("console.log 1");
    process.nextTick(() => console.log("this is process.nextTick 1"));
    console.log("console.log 2");

    输出

    console.log 1
    console.log 2
    this is process.nextTick 1

    结论: 同步先于异步

    实验2

    // index.js
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    process.nextTick(() => console.log("this is process.nextTick 1"));

    输出

    this is process.nextTick 1
    this is Promise.resolve 1

    结论: nextTick先于promise

    实验3

    // index.js
    process.nextTick(() => console.log("this is process.nextTick 1"));
    process.nextTick(() => {
      console.log("this is process.nextTick 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside next tick")
      );
    });
    process.nextTick(() => console.log("this is process.nextTick 3"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    Promise.resolve().then(() => {
      console.log("this is Promise.resolve 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside Promise then block")
      );
    });
    Promise.resolve().then(() => console.log("this is Promise.resolve 3"));

    实验3

    // index.js
    process.nextTick(() => console.log("this is process.nextTick 1"));
    process.nextTick(() => {
      console.log("this is process.nextTick 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside next tick")
      );
    });
    process.nextTick(() => console.log("this is process.nextTick 3"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    Promise.resolve().then(() => {
      console.log("this is Promise.resolve 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside Promise then block")
      );
    });
    Promise.resolve().then(() => console.log("this is Promise.resolve 3"));

    输出

    this is process.nextTick 1
    this is process.nextTick 2
    this is process.nextTick 3
    this is the inner next tick inside next tick
    this is Promise.resolve 1
    this is Promise.resolve 2
    this is Promise.resolve 3
    this is the inner next tick inside Promise then block

    解析:

    nextTick内部增加的nextTick任务还是先于promise,因为nexttick队列清完后才会执行promise队列的任务。

    promise里增加的nextTick任务晚于其他的promise,因为此时是在执行promise阶段,需要清空promise才会检查nextTick队列。

    实验4

    // index.js
    setTimeout(() => console.log("this is setTimeout 1"), 0);
    setTimeout(() => {
      console.log("this is setTimeout 2");
      process.nextTick(() =>
        console.log("this is inner nextTick inside setTimeout")
      );
    }, 0);
    setTimeout(() => console.log("this is setTimeout 3"), 0);
    process.nextTick(() => console.log("this is process.nextTick 1"));
    process.nextTick(() => {
      console.log("this is process.nextTick 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside next tick")
      );
    });
    process.nextTick(() => console.log("this is process.nextTick 3"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    Promise.resolve().then(() => {
      console.log("this is Promise.resolve 2");
      process.nextTick(() =>
        console.log("this is the inner next tick inside Promise then block")
      );
    });
    Promise.resolve().then(() => console.log("this is Promise.resolve 3"));

    输出

    this is process.nextTick 1
    this is process.nextTick 2
    this is process.nextTick 3
    his is the inner next tick inside next tick
    this is Promise.resolve 1
    this is Promise.resolve 2
    this is Promise.resolve 3
    this is the inner next tick inside Promise then block
    this is setTimeout 1
    this is setTimeout 2
    this is inner nextTick inside setTimeout
    this is setTimeout 3

    结论:

    nextTick先于promise;微任务先于setTimeout;每个Timer任务后会检查执行微任务。

    实验6

    // index.js
    setTimeout(() => console.log("this is setTimeout 1"), 1000);
    setTimeout(() => console.log("this is setTimeout 2"), 500);
    setTimeout(() => console.log("this is setTimeout 3"), 0);

    输出

    this is setTimeout 3
    this is setTimeout 2
    this is setTimeout 1

    结论: Timer队列是按时间排序的

    实验7

    // index.js
    const fs = require("fs");
    fs.readFile(__filename, () => {
      console.log("this is readFile 1");
    });
    process.nextTick(() => console.log("this is process.nextTick 1"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));

    输出

    this is process.nextTick 1
    this is Promise.resolve 1

    结论:微任务先于io任务

    实验8

    // index.js
    const fs = require("fs");
    setTimeout(() => console.log("this is setTimeout 1"), 0);
    fs.readFile(__filename, () => {
      console.log("this is readFile 1");
    });

    输出

    不确定

    解析:setTimeout 0通常内部会取1ms,也就是1ms后执行Timer任务,而cpu进入事件循环的时机不定,所以有可能进入事件循环时已经过了1ms,那么先执行timer任务,也可能进入时定时任务没到时间,会先执行IO任务。

    实验9

    // index.js
    const fs = require("fs");
    fs.readFile(__filename, () => {
      console.log("this is readFile 1");
    });
    process.nextTick(() => console.log("this is process.nextTick 1"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    setTimeout(() => console.log("this is setTimeout 1"), 0);
    for (let i = 0; i < 2000000000; i++) {}

    输出

    this is process.nextTick 1
    this is Promise.resolve 1
    this is setTimeout 1
    this is readFile 1

    解析:

    代码最后加了循环保证进入事件循环时定时器任务已经到期,所以先执行Timer任务

    实验10

    // index.js
    const fs = require("fs");
    fs.readFile(__filename, () => {
      console.log("this is readFile 1");
    });
    process.nextTick(() => console.log("this is process.nextTick 1"));
    Promise.resolve().then(() => console.log("this is Promise.resolve 1"));
    setTimeout(() => console.log("this is setTimeout 1"), 0);
    setImmediate(() => console.log("this is setImmediate 1"));
    for (let i = 0; i < 2000000000; i++) {}

    输出

    this is process.nextTick 1
    this is Promise.resolve 1
    this is setTimeout 1
    this is setImmediate 1
    this is readFile 1

    解析: 按理说IO任务先于check任务,但是第一次事件循环时IO任务的callback并不在队列里。在两个队列之间会通过IO polling的方式去查看io任务是否完成,完成了就将callback加到队列里,然后下一轮循环时会调用

    感谢各位的阅读,以上就是“nodeJs事件循环运行代码怎么写”的内容了,经过本文的学习后,相信大家对nodeJs事件循环运行代码怎么写这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI