详解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 相关文章推荐
Maps Javascript
Jan 22 Javascript
IE7中javascript操作CheckBox的checked=true不打勾的解决方法
Dec 07 Javascript
JavaScript中String和StringBuffer的速度之争
Apr 01 Javascript
Jquery练习之表单验证实现代码
Dec 14 Javascript
IE6、IE7中setAttribute不支持class/for/rowspan/colspan等属性
Aug 28 Javascript
JQuery中form验证出错信息的查看方法
Oct 08 Javascript
随鼠标移动的时钟非常漂亮遗憾的是只支持IE
Aug 12 Javascript
深入浅析AngularJS和DataModel
Feb 16 Javascript
浅谈时钟的生成(js手写简洁代码)
Aug 20 Javascript
angular实现form验证实例代码
Jan 17 Javascript
AngularJs 最新验证手机号码的实例,成功测试通过
Nov 26 Javascript
微信小程序入门之绘制时钟
Oct 22 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+ajax实时输入自动搜索匹配的方法
2014/12/26 PHP
浅谈PHP中foreach/in_array的使用
2015/11/02 PHP
浅谈Laravel POST,PUT,PATCH 路由的区别
2019/10/15 PHP
jquery 将disabled的元素置为enabled的三种方法
2009/07/25 Javascript
jQuery实现的导航条切换可显示隐藏
2014/10/22 Javascript
jQuery中prependTo()方法用法实例
2015/01/08 Javascript
JS判断字符串包含的方法
2015/05/05 Javascript
jQuery on()方法绑定动态元素的点击事件实例代码浅析
2016/06/16 Javascript
jQuery实现查找最近父节点的方法
2016/06/23 Javascript
基于JavaScript实现Tab选项卡切换效果
2016/11/24 Javascript
JavaScript登录记住密码操作(超简单代码)
2017/03/22 Javascript
浅谈node的事件机制
2017/10/09 Javascript
JS中移除非数字最多保留一位小数
2018/05/09 Javascript
Vue中的作用域CSS和CSS模块的区别
2018/10/09 Javascript
JS面向对象之单选框实现
2020/01/17 Javascript
JS表单验证插件之数据与逻辑分离操作实例分析【策略模式】
2020/05/01 Javascript
JavaScript中的执行环境和作用域链
2020/09/04 Javascript
[50:29]2014 DOTA2华西杯精英邀请赛 5 24 DK VS iG
2014/05/26 DOTA
python读取Android permission文件
2013/11/01 Python
python安装教程
2018/02/28 Python
浅谈flask源码之请求过程
2018/07/26 Python
Python turtle画图库&&画姓名实例
2020/01/19 Python
使用Python爬取弹出窗口信息的实例
2020/03/14 Python
python库skimage给灰度图像染色的方法示例
2020/04/27 Python
CSS3 实现弹跳的小球动画
2020/10/26 HTML / CSS
怀俄明州飞钓:Platte River Fly Shop
2017/12/28 全球购物
关于Assembly命名空间的三个面试题
2015/07/23 面试题
局域网定义和特性
2016/01/23 面试题
应届实习生的自我评价范文
2014/01/05 职场文书
给老师的道歉信
2014/01/11 职场文书
日语专业个人求职信范文
2014/02/02 职场文书
项目投资意向书
2014/04/01 职场文书
大学生简短的自我评价
2014/09/12 职场文书
新闻发布会活动策划方案
2014/09/15 职场文书
2014年驻村干部工作总结
2014/11/17 职场文书
2015年推普周活动方案
2015/05/06 职场文书