这篇文章主要讲解了“nodejs事件循环运行代码怎么写”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs事件循环运行代码怎么写”吧!Nodejs运行时JS语言是同步,阻塞,单线程的,
这篇文章主要讲解了“nodejs事件循环运行代码怎么写”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs事件循环运行代码怎么写”吧!
JS语言是同步,阻塞,单线程的,但是nodejs不是。Nodejs由三个主要组件:
nodejs的异步特性主要由libuv提供。libuv是跨平台的使用C语言写的库,它主要提供对异步操作的支持。
当我们在Nodejs中执行JS代码时,是由v8引擎处理代码执行,v8包括一块内存区域(堆)和调用栈。当定义函数,变量时,从堆中分配内存,当执行代码时将函数入栈,函数返回时出栈。
当执行异步操作时,libuv将接管该任务,然后使用操作系统的异步机制运行任务。如果缺乏系统级的异步机制,就使用线程池运行任务,保证主线程不被阻塞。
事件循环是一个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.jsconsole.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.jsPromise.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.jsprocess.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.jsprocess.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.jssetTimeout(() => 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 1this is process.nextTick 2this is process.nextTick 3his is the inner next tick inside next tickthis is Promise.resolve 1this is Promise.resolve 2this is Promise.resolve 3this is the inner next tick inside Promise then blockthis is setTimeout 1this is setTimeout 2this is inner nextTick inside setTimeoutthis is setTimeout 3
结论:
nextTick先于promise;微任务先于setTimeout;每个Timer任务后会检查执行微任务。
实验6
// index.jssetTimeout(() => 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.jsconst 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.jsconst 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.jsconst 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.jsconst 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事件循环运行代码怎么写这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!
--结束END--
本文标题: nodeJs事件循环运行代码怎么写
本文链接: https://www.lsjlt.com/news/357687.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
2024-05-16
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0