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();
  • 1
  • 2
  • 3

它的执行逻辑是,先询问事件观察者当前是否有任务需要执行?观察者回答“有”,于是取出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"); });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

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

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

1、原始代码:

A();
B();
C();
  • 1
  • 2
  • 3

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

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

A();
process.nextTick(B);
C();
  • 1
  • 2
  • 3

它的执行顺序如下:

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

A();
setImmediate(B);//或者setTimeout(B,0);
C();
  • 1
  • 2
  • 3

它的执行顺序如下:

Microtasks Macrotasks

任务队列不止一个,还有 microtasks 和 macrotasks

microtasks:

  • process.nextTick
  • promise
  • Object.observe
  • MutationObserver

macrotasks:

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI渲染
  • 一个事件循环(event loop)会有一个或多个任务队列(task queue)
  • task queue 就是 macrotask queue
  • 每一个 event loop 都有一个 microtask queue
  • task queue == macrotask queue != microtask queue
  • 一个任务 task 可以放入 macrotask queue 也可以放入 microtask queue 中

理解了这些定义之后,再看执行原理:

事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。

还要注意一点:

包裹在一个 script 标签中的js代码也是一个 task 确切说是 macrotask。

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

idea观察者 > IO观察者 > check观察者

process.nextTick > setTimeout > setImmediate

console.log('start')const interval = setInterval(() => { console.log('setInterval') }, 0) setTimeout(() => { console.log('setTimeout 1') Promise.resolve() .then(() => { console.log('promise 3') }) .then(() => { console.log('promise 4') }) .then(() => { setTimeout(() => { console.log('setTimeout 2') Promise.resolve() .then(() => { console.log('promise 5') }) .then(() => { console.log('promise 6') }) .then(() => { clearInterval(interval) }) }, 0) }) }, 0) Promise.resolve() .then(() => { console.log('promise 1') }) .then(() => { console.log('promise 2') }) 

start promise 1 promise 2 setInterval setTimeout 1 promise 3 promise 4 setInterval setTimeout 2 promise 5 promise 6

转载于:https://www.cnblogs.com/qqxwbtt/p/7825150.html

setTimeout(), nextTick(),setImmediate()区别 ZT~相关推荐

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

    node.js中的非IO的异步API提供了四种方法,分别为setTimeOut(),setInterval(),setImmediate()以及process.nextTick(),四种方法实现原理相 ...

  2. setTimeout和setImmediate以及process.nextTick的区别

    <第二届阿里巴巴前端练习生计划线上笔试>考试 setTimeout和setImmediate以及process.nextTick的区别 SetTimeOut setTimeout和setI ...

  3. 前端碎碎念 之 nextTick, setTimeout 以及 setImmediate 三者的执行顺序

    『前端碎碎念』系列会记录我平时看书或者看文章遇到的问题,一般都是比较基础但是容易遗忘的知识点,你也可能会在面试中碰到. 我会查阅一些资料并可能加上自己的理解,来记录这些问题.更多文章请前往我的个人博客 ...

  4. js setTimeout和setInterval区别

    1.区别 2.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&qu ...

  5. setInterval和setTimeout的使用区别

    setTimeout和setInterval的使用 这两个方法都可以用来实现在一个固定时间段之后去执行JavaScript.不过两者各有各的应用场景. 方 法 实际上,setTimeout和setIn ...

  6. Http和Socket连接区别(ZT)

    1.TCP连接 要想明白Socket连接,先要明白TCP连接.手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上 ...

  7. setTimeOut与 setInterval区别

    当调用 windows.setTimeOut("add()",3000); 意味着 3秒之后调用add()方法 调用       window.setIn terval(" ...

  8. javascript setTimeout 和 setInterval 区别

    [setTimeout] setTimeout(表达式,延时时间) 在执行时,是在载入后延迟指定时间后,去执行一次表达式,记住,次数 是一次 用setTimeout实现的自动变化显示随机数的效果: & ...

  9. setTimeout和setInterval区别,以及定时器的传参功能

    setTimeout和setInterval都属性Javascript中的定时器,可以规定延迟时间再执行某个操作,不同的是setTimeout在规定时间后执行完某个操作就停止了,而setInterva ...

  10. 前端面试问到setTImeout与setInterval区别

    基础知识 setTimeout 超时调用,超过时间T,就执行fn setInterval 间歇调用,调用周期t,执行fn 相同点 二者调用后均返回数值ID,可以用来取消. 清除setInterval比 ...

最新文章

  1. 蓝桥杯四平方和Java_蓝桥杯 四平方和
  2. python零基础能学吗 知乎-Python零基础学习能学好吗?老男孩Python面授班
  3. Jenkins 技术篇-jenkins的下载、安装与配置
  4. runat=server
  5. 不借助Maven,使用Eclipse创建Hello World级别的Spring项目
  6. python读excel两列为字典_用python读取Excel并保存字典?一两行代码完成骚操作
  7. 轻量级文本编辑器,Notepad最佳替代品:Notepad++
  8. 【动态规划】石子合并
  9. 浅谈GPRS的几种应用方案
  10. 前端性能优化经典:javascript防抖节流
  11. zero to one (2)
  12. 用计算机探索规律概括,《用计算器探索规律》优秀教学设计
  13. excel使用教程_如何系统地学习Excel?
  14. 第四课曲面与曲线方程
  15. 响应式2022英文企业官网源码,感觉挺有创意的
  16. 基于netty实现gps jtt808协议接入
  17. 封装获取非行内样式函数
  18. 手机APP测试注意点
  19. 科学计算机 app,‎App Store 上的“超级计算器-科学计算机”
  20. 不用编程 实现西门子PLC和罗克韦尔AB PLC的通讯和协议转换

热门文章

  1. 时间序列的归一化方法
  2. EMNLP'21 | 基于互指导和句间关系图的论点对抽取
  3. 【论文】本周论文推荐(11.23-11.29)
  4. 深度学习2.0-15.随机梯度下降之梯度下降简介
  5. 深度学习2.0-1.tensorflow的基础操作之数据类型
  6. Anaconda的安装和环境使用
  7. 自然语言处理——用逻辑回归来实现情绪识别
  8. 机器学习和数据挖掘的联系与区别
  9. PostgreSQL逻辑优化——查询优化分析
  10. 面向对象设计必须学习的三层应用程序模型