详解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 相关文章推荐
javascript 闭包
Sep 15 Javascript
使用javascript控制cookie显示和隐藏背景图
Feb 12 Javascript
JavaScript获取DOM元素的11种方法总结
Apr 25 Javascript
JS实现可展开折叠层的鼠标拖曳效果
Oct 09 Javascript
jQuery动画效果相关方法实例分析
Dec 31 Javascript
Node.js测试中的Mock文件系统详解
Nov 21 Javascript
angularjs实现上拉加载和下拉刷新数据功能
Jun 12 Javascript
基于JS递归函数细化认识及实用实例(推荐)
Aug 07 Javascript
微信小程序删除处理详解
Aug 16 Javascript
原生JS封装animate运动框架的实例
Oct 12 Javascript
Angular实现双向折叠列表组件的示例代码
Nov 21 Javascript
原生JavaScript实现购物车
Jan 10 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
用PHP4访问Oracle815
2006/10/09 PHP
不用数据库的多用户文件自由上传投票系统(2)
2006/10/09 PHP
目录,文件操作详谈―PHP
2006/11/25 PHP
php实现处理输入转义字符的代码
2015/11/08 PHP
详解php语言最牛掰的Laravel框架
2017/11/20 PHP
php传值和传引用的区别点总结
2019/11/19 PHP
倒记时60刷新网页的js代码
2014/02/18 Javascript
javascript实现多级联动下拉菜单的方法
2015/02/06 Javascript
使用jquery清空、复位整个输入域
2015/04/02 Javascript
JavaScript表格常用操作方法汇总
2015/04/15 Javascript
jquery实现网页的页面平滑滚动效果代码
2015/11/02 Javascript
Jquery $when done then的用法详解
2016/05/20 Javascript
NodeJS配置HTTPS服务实例分享
2017/02/19 NodeJs
node使用UEditor富文本编辑器的方法实例
2017/07/11 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
基于node.js实现微信支付退款功能
2017/12/19 Javascript
Vue-cli中为单独页面设置背景色的实现方法
2018/02/11 Javascript
JavaScript Blob对象原理及用法详解
2020/10/14 Javascript
通过5个知识点轻松搞定Python的作用域
2016/09/09 Python
Python、PyCharm安装及使用方法(Mac版)详解
2017/04/28 Python
python使用opencv读取图片的实例
2017/08/17 Python
python通过opencv实现批量剪切图片
2017/11/13 Python
Python中内建模块collections如何使用
2020/05/27 Python
python给视频添加背景音乐并改变音量的具体方法
2020/07/19 Python
有关pycharm登录github时有的时候会报错connection reset的问题
2020/09/15 Python
用纯css3和html制作泡沫对话框实现代码
2013/03/21 HTML / CSS
详解HTML5 Canvas标签及基本使用
2020/01/10 HTML / CSS
美国电子产品折扣网站:Daily Steals
2017/05/20 全球购物
土耳其时尚潮流在线购物网站:Trendyol
2017/10/10 全球购物
TUMI新加坡官网:国际领先的商旅箱包品牌
2019/01/12 全球购物
计算机网络专业求职信
2014/06/05 职场文书
2014年后勤工作总结范文
2014/12/16 职场文书
2015年后勤工作总结范文
2015/04/08 职场文书
实用求职信模板范文
2019/05/13 职场文书
导游词之西安骊山
2019/12/20 职场文书
如何用JS实现网页瀑布流布局
2021/04/24 Javascript