详解promise.then,process.nextTick, setTimeout 以及 setImmediate的执行顺序


Posted in Javascript onNovember 21, 2018

本文介绍了详解promise.then,process.nextTick, setTimeout 以及 setImmediate的执行顺序,分享给大家,具体如下:

先举一个比较典型的例子:

setImmediate(function(){
  console.log(1);
},0);
setTimeout(function(){
  console.log(2);
},0);
new Promise(function(resolve){
  console.log(3);
  resolve();
  console.log(4);
}).then(function(){
  console.log(5);
});
console.log(6);
process.nextTick(function(){
  console.log(7);
});
console.log(8);

这段代码输出的正确顺序是什么?

答案是:

3 4 6 8 7 5 2 1

在解释输出结果之前,我们来看几个概念:

macro-task: script (整体代码),setTimeout, setInterval, setImmediate, I/O, UI rendering.

micro-task: process.nextTick, Promise(原生),Object.observe,MutationObserver

第一步. script整体代码被执行,执行过程为

  • 创建setImmediate macro-task
  • 创建setTimeout macro-task
  • 创建micro-task Promise.then 的回调,并执行script console.log(3); resolve(); console.log(4); 此时输出3和4,虽然resolve调用了,执行了但是整体代码还没执行完,无法进入Promise.then 流程。
  • console.log(6)输出6
  • process.nextTick 创建micro-task
  • console.log(8) 输出8
  • 第一个过程过后,已经输出了3 4 6 8

第二步. 由于其他micro-task 的 优先级高于macro-task。

此时micro-task 中有两个任务按照优先级process.nextTick 高于 Promise。

所以先输出7,再输出5

第三步,micro-task 任务列表已经执行完毕,家下来执行macro-task. 由于setTimeout的优先级高于setIImmediate,所以先输出2,再输出1。

整个过程描述起来像是同步操作,实际上是基于Event Loop的事件循环

关于micro-task和macro-task的执行顺序,可看下面这个例子(来自《深入浅出Node.js》):

//加入两个nextTick的回调函数
process.nextTick(function () {
  console.log('nextTick延迟执行1');
});
process.nextTick(function () { 
  console.log('nextTick延迟执行2');
});
// 加入两个setImmediate()的回调函数
setImmediate(function () {
  console.log('setImmediate延迟执行1'); 
  // 进入下次循环 
  process.nextTick(function () {
    console.log('强势插入');
  });
});
setImmediate(function () {
  console.log('setImmediate延迟执行2'); 
});

console.log('正常执行');

运行这段代码,结果是这样:

正常执行
nextTick延迟执行1
nextTick延迟执行2
setImmediate延迟执行1
setImmediate延迟执行2
强势插入

在新版的Node中,process.nextTick执行完后,会循环遍历setImmediate,将setImmediate都执行完毕后再跳出循环。所以两个setImmediate执行完后队列里只剩下第一个setImmediate里的process.nextTick。最后输出”强势插入”。

关于优先级的另一个比较清晰的版本:

观察者优先级

在每次轮训检查中,各观察者的优先级分别是:

idle观察者 > I/O观察者 > check观察者。

idle观察者:process.nextTick

I/O观察者:一般性的I/O回调,如网络,文件,数据库I/O等

check观察者:setTimeout>setImmediate

总结

  • 同步代码执行顺序优先级高于异步代码执行顺序优先级;
  • new Promise(fn)中的fn是同步执行;
  • process.nextTick()>Promise.then()>setTimeout>setImmediate。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
web前端开发也需要日志
Dec 09 Javascript
Javascript中的数组常用方法解析
Jun 17 Javascript
用js实现简单算法的实例代码
Sep 24 Javascript
JavaScript 轮播图和自定义滚动条配合鼠标滚轮分享代码贴
Oct 28 Javascript
微信小程序 图片宽度自适应的实现
Apr 06 Javascript
BootStrap 动态表单效果
Jun 02 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
Sep 25 Javascript
vue.js input框之间赋值方法
Aug 24 Javascript
vue 实现左右拖拽元素并且不超过他的父元素的宽度
Nov 30 Javascript
vue组件文档(.md)中如何自动导入示例(.vue)详解
Jan 25 Javascript
详解从0开始搭建微信小程序(前后端)的全过程
Apr 15 Javascript
详解js根据百度地图提供经纬度计算两点距离
May 13 Javascript
Nuxt.js之自动路由原理的实现方法
Nov 21 #Javascript
nuxt.js中间件实现拦截权限判断的方法
Nov 21 #Javascript
Nuxt.js SSR与权限验证的实现
Nov 21 #Javascript
详解nuxt路由鉴权(express模板)
Nov 21 #Javascript
使用vue-cli webpack 快速搭建项目的代码
Nov 21 #Javascript
Angular刷新当前页面的实现方法
Nov 21 #Javascript
详解ES6系列之私有变量的实现
Nov 21 #Javascript
You might like
php产生随机数的两种方法实例代码 输出随机IP
2011/04/08 PHP
php循环语句 for()与foreach()用法区别介绍
2012/09/05 PHP
使用Codeigniter重写insert的方法(推荐)
2017/03/23 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
js获取电脑分辨率的思路及操作
2013/11/22 Javascript
node.js中的fs.openSync方法使用说明
2014/12/17 Javascript
浅析javascript 定时器
2014/12/23 Javascript
【JS+CSS3】实现带预览图幻灯片效果的示例代码
2016/03/17 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
Bootstrap CSS布局之表单
2016/12/17 Javascript
jQuery实现三级联动效果
2017/03/02 Javascript
node.js中使用Export和Import的方法
2017/09/18 Javascript
jQuery HTML css()方法与css类实例详解
2020/05/20 jQuery
vue基础知识--axios合并请求和slot
2020/06/04 Javascript
js实现简单的无缝轮播效果
2020/09/05 Javascript
windows如何把已安装的nodejs高版本降级为低版本(图文教程)
2020/12/14 NodeJs
[50:02]完美世界DOTA2联赛PWL S2 Magma vs FTD 第三场 11.29
2020/12/03 DOTA
gearman的安装启动及python API使用实例
2014/07/08 Python
Python基于回溯法子集树模板解决野人与传教士问题示例
2017/09/11 Python
Python实现的大数据分析操作系统日志功能示例
2019/02/11 Python
Python 使用生成器代替线程的方法
2020/08/04 Python
python实现企业微信定时发送文本消息的示例代码
2020/11/24 Python
Canvas制作的下雨动画的示例
2018/03/06 HTML / CSS
软件测试英文面试题
2012/10/14 面试题
What is EJB
2016/07/22 面试题
大四自我鉴定
2014/02/08 职场文书
党组织公开承诺书
2014/03/29 职场文书
电子装配专业毕业生求职信
2014/04/23 职场文书
教师反腐倡廉演讲稿
2014/09/03 职场文书
实习指导教师评语
2014/12/30 职场文书
国庆节慰问信
2015/02/15 职场文书
2015年爱牙日活动总结
2015/03/23 职场文书
2015年度合同管理工作总结
2015/05/22 职场文书
python实现批量移动文件
2021/04/05 Python
python实现简单倒计时功能
2021/04/21 Python
分享几个实用的CSS代码块
2022/06/10 HTML / CSS