详解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 相关文章推荐
超简单的jquery的AJAX用法
May 10 Javascript
jquery实现的带缩略图的焦点图片切换(自动播放/响应鼠标动作)
Jan 23 Javascript
js将json格式内容转换成对象的方法
Nov 01 Javascript
深入解析JavaScript框架Backbone.js中的事件机制
Feb 14 Javascript
CascadeView级联组件实现思路详解(分离思想和单链表)
Apr 12 Javascript
JS中的数组方法笔记整理
Jul 26 Javascript
轻松搞定js表单验证
Oct 13 Javascript
浅谈JavaScript的函数及作用域
Dec 30 Javascript
JavaScript 中定义函数用 var foo = function () {} 和 function foo()区别介绍
Mar 01 Javascript
JS实现的全选、全不选及反选功能【案例】
Feb 19 Javascript
Node.js如何优雅的封装一个实用函数的npm包的方法
Apr 29 Javascript
深入了解JavaScript代码覆盖
Jun 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中生成随机密码的自定义函数代码
2013/10/21 PHP
PHP中使用TCPDF生成PDF文档实例
2014/07/01 PHP
php采用curl模仿登录人人网发布动态的方法
2014/11/07 PHP
PHP面向对象之后期静态绑定功能介绍
2015/05/18 PHP
学习php设计模式 php实现状态模式
2015/12/07 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
2016/03/23 PHP
浅析PHP7的多进程及实例源码
2019/04/14 PHP
javascript 一个自定义长度的文本自动换行的函数
2007/08/19 Javascript
使用jquery给input和textarea设定ie中的focus
2008/05/29 Javascript
javascript prototype 原型链
2009/03/12 Javascript
原生javaScript做得动态表格(注释写的很清楚)
2013/12/29 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
AngularJS 视图详解及示例代码
2016/08/17 Javascript
Node.js读取文件内容示例
2017/03/07 Javascript
详解vue-cli中配置sass
2017/06/21 Javascript
jQuery EasyUI 折叠面板accordion的使用实例(分享)
2017/12/25 jQuery
利用js给datalist或select动态添加option选项的方法
2018/01/25 Javascript
angular4 JavaScript内存溢出问题
2018/03/06 Javascript
JavaScript fetch接口案例解析
2018/08/30 Javascript
JS散列表碰撞处理、开链法、HashTable散列示例
2019/02/08 Javascript
Nodejs 识别图片类型的方法
2019/08/15 NodeJs
浅谈layui框架自带分页和表格重载的接口解析问题
2019/09/11 Javascript
刷新页面后让控制台的js代码继续执行
2019/09/20 Javascript
JavaScript禁止右击保存图片,禁止拖拽图片的实现代码
2020/04/28 Javascript
[10:39]DOTA2上海特级锦标赛音乐会纪录片
2016/03/21 DOTA
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
解决Python print 输出文本显示 gbk 编码错误问题
2018/07/13 Python
使用python获取(宜宾市地震信息)地震信息
2019/06/20 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
基于python生成英文版词云图代码实例
2020/05/16 Python
css3.0新属性效果在ie下的解决方案
2010/05/10 HTML / CSS
使用HTML5在网页中嵌入音频和视频播放的基本方法
2016/02/22 HTML / CSS
6PM官网:折扣鞋、服装及配饰
2018/08/03 全球购物
签约仪式主持词
2014/03/19 职场文书
机械电子工程专业求职信
2014/06/22 职场文书
英文演讲稿开场白
2014/08/25 职场文书