当前位置: 首页 > news >正文

细说setTimeout/setImmediate/process.nextTick的区别

node.js中的非IO的异步API提供了四种方法,分别为setTimeOut(),setInterval(),setImmediate()以及process.nextTick(),四种方法实现原理相似,但达到的效果略有区别:

一、事件循环Event Loop

首先,我们需要了解node.js的基于事件循环的事件模型,正是因为它才使得node.js中回调函数十分普遍,也正是基于此,node.js实现了单线程高效的异步IO(这里说的单线程主要说的是执行javascript代码部分的线程,而异步IO部分node.js其实还是利用线程池去执行的)。

简单的讲就是,在node.js启动时,创建了一个类似while(true)的循环体,每次执行一次循环体称为一次tick,每个tick的过程就是查看是否有事件等待处理,如果有,则取出事件极其相关的回调函数并执行,然后执行下一次tick。所以,有如下代码:

A();
B();
C();
复制代码

它的执行逻辑是,先询问事件观察者当前是否有任务需要执行?观察者回答“有”,于是取出A执行,A是否有回调函数?如果有(如果没有则继续询问当前是否有任务需要执行),则取出回调函数并执行(注意:回调函数的执行基本都是异步的,可能不止一个回调),执行完回调后通过某种方式通知调用者,我执行完了,并把执行结果给你,你自己酌情处理吧,主函数不需要不断询问回调函数执行结果,回调函数会以通知的方式告知调用者我执行完了(don’t call me ,i will call you.),而这个过程主线程并不需要等待回调函数执行完成,它会继续向前执行,即再次询问观察者当前是否还有任务需要执行,重复上面的步骤。。。直到观察者回答没有了,线程结束。

整个事件循环的逻辑如下图:

二、setTimeOut(),setInterval(),setImmediate()以及process.nextTik()

这里面setTimeOut()与setInterval()除了执行频次外基本相同,都表示主线程执行完一定时间后立即执行,而setImmediate()与之十分相似,也表示主线程执行完成后立即执行。那么他们之间的区别是什么呢?

代码如下:

setTimeout(function(){
    console.log("setTimeout");
},0);

setImmediate(function(){
    console.log("setImmediate");
});
复制代码

两者都代表主线程完成后立即执行,其执行结果是不确定的,可能是setTimeout回调函数执行结果在前,也可能是setImmediate回调函数执行结果在前,但setTimeout回调函数执行结果在前的概率更大些,这是因为他们采用的观察者不同,setTimeout采用的是类似IO观察者,setImmediate采用的是check观察者,而process.nextTick()采用的是idle观察者

三种观察者的优先级顺序是:idle观察者>>io观察者>check观察者

process.nextTick()与setImmediate()和setTimeout()的区别如下:

1、原始代码:

A();
B();
C();
复制代码

它的执行顺序即代码顺序:

2、process.nextTick()执行效果,代码如下:

A();
process.nextTick(B);
C();
复制代码

它的执行顺序如下:

3、setImmediate()或者setTimeout()执行效果,代码如下:

A();
setImmediate(B);//或者setTimeout(B,0);
C();
复制代码

它的执行顺序如下:

结论:
process.nextTick(),效率最高,消费资源小,但会阻塞CPU的后续调用; setTimeout(),精确度不高,可能有延迟执行的情况发生,且因为动用了红黑树,所以消耗资源大;
setImmediate(),消耗的资源小,也不会造成阻塞,但效率也是最低的。

转载https://blog.csdn.net/hkh_1012/article/details/53453138

相关文章:

  • ORA-28040: No matching authentication protocol
  • chmod-chown-umask-lsattr-chattr
  • java实现图片转ascii字符画
  • [CF494C]Helping People
  • oracle自带函数
  • 菜鸟要投120亿港币,在香港建超级eHub
  • 装修设计解剖书
  • BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
  • JQuery实现聊天对话框
  • 神级python程序员只需要一个公众号,再也不会错过重要资讯
  • E盘可用空间0字节,要怎样找到文件
  • jenkins详解(一)
  • C# API中的模型和它们的接口设计
  • [日常] 算法-单链表的创建-尾插法
  • 苹果发布Core ML 2
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • CSS实用技巧干货
  • Electron入门介绍
  • ES6语法详解(一)
  • HTML中设置input等文本框为不可操作
  • Java知识点总结(JDBC-连接步骤及CRUD)
  • mysql innodb 索引使用指南
  • Mysql数据库的条件查询语句
  • Redis 懒删除(lazy free)简史
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • Sublime text 3 3103 注册码
  • vue数据传递--我有特殊的实现技巧
  • 猴子数据域名防封接口降低小说被封的风险
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 区块链技术特点之去中心化特性
  • 阿里云服务器如何修改远程端口?
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (转)Sublime Text3配置Lua运行环境
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .NET 4.0中的泛型协变和反变
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET6实现破解Modbus poll点表配置文件