详解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 JSON操作入门实例
Apr 16 Javascript
基于jQuery的表格操作插件
Apr 22 Javascript
jquery中常用的函数和属性详细解析
Mar 07 Javascript
jquery 操作css样式、位置、尺寸方法汇总
Nov 28 Javascript
利用js编写响应式侧边栏
Sep 17 Javascript
ES6中参数的默认值语法介绍
May 03 Javascript
在 webpack 中使用 ECharts的实例详解
Feb 05 Javascript
vue 中基于html5 drag drap的拖放效果案例分析
Nov 01 Javascript
vue自定义指令directive的使用方法
Apr 07 Javascript
Nautil 中使用双向数据绑定的实现
Oct 02 Javascript
Centos7 安装Node.js10以上版本的方法步骤
Oct 15 Javascript
vue 监听 Treeselect 选择项的改变操作
Aug 31 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通过正则表达式下载图片到本地的实现代码
2011/09/19 PHP
php实现通用的从数据库表读取数据到数组的函数实例
2015/03/21 PHP
Laravel 5.3 学习笔记之 配置
2016/08/28 PHP
PHP进程通信基础之信号量与共享内存通信
2017/02/19 PHP
PHP实现的各类hash算法长度及性能测试实例
2017/08/27 PHP
Thinkphp框架使用list_to_tree 实现无限级分类列出所有节点示例
2020/04/04 PHP
动态显示可输入的字数提示还可以输入的字数
2014/04/01 Javascript
js取得html iframe中的元素和变量值
2014/06/30 Javascript
返回顶部按钮响应滚动且动态显示与隐藏
2014/10/14 Javascript
js实现同一页面可多次调用的图片幻灯切换效果
2015/02/28 Javascript
Bootstrap入门书籍之(四)菜单、按钮及导航
2016/02/17 Javascript
微信小程序  modal弹框组件详解
2016/10/27 Javascript
JavaScript数组的5种迭代方法
2017/09/29 Javascript
vue 使用html2canvas将DOM转化为图片的方法
2018/09/11 Javascript
vue 中的 render 函数作用详解
2020/02/28 Javascript
javascript实现下拉菜单效果
2021/02/09 Javascript
python正则匹配抓取豆瓣电影链接和评论代码分享
2013/12/27 Python
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
Python写入数据到MP3文件中的方法
2015/07/10 Python
解决Pycharm运行时找不到文件的问题
2018/10/29 Python
Pandas之Fillna填充缺失数据的方法
2019/06/25 Python
Python+OpenCV+pyQt5录制双目摄像头视频的实例
2019/06/28 Python
详解python实现交叉验证法与留出法
2019/07/11 Python
浅谈python已知元素,获取元素索引(numpy,pandas)
2019/11/26 Python
基于python爬取有道翻译过程图解
2020/03/31 Python
Python Flask异步发送邮件实现方法解析
2020/08/01 Python
python如何实现DES加密
2020/09/21 Python
美国小蜜蜂Burt’s Bees德国官网:天然唇部、皮肤和身体护理产品
2020/06/14 全球购物
银行员工辞职信范文
2014/01/20 职场文书
劲霸男装广告词
2014/03/21 职场文书
2014党员学习兰辉先进事迹思想汇报
2014/09/17 职场文书
“四风”问题自我剖析材料思想汇报
2014/09/23 职场文书
小学假期安全广播稿
2014/09/28 职场文书
幼师小班个人总结
2015/02/12 职场文书
jquery插件实现代码雨特效
2021/04/24 jQuery
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技