宏任务
script,setTimeoout,setInterval,setlmmediate(node 独有),I/o,render渲染
微任务
process.nextTick(),promise 
1,执行timers阶段,执行setTimeOut()和setInterval到期的calback
2,I/O callbacks: 上一轮循环中少数callback/Io会被延迟到这一阶段执行
3,idle,prepare:队列的移动紧内部实现
4,poll:执行I/O,适当的条件下会阻塞这个阶段
5,check:执行setlmmediate的calback
6,close calback:执行close 事件的calback
1,1 例子
浏览器和node执行顺序的区别
setTimeout(()=>{
    console.log('timer1')
    Promise.resolve().then(function() {
        console.log('promise1')
    })
}, 0)
setTimeout(()=>{
    console.log('timer2')
    Promise.resolve().then(function() {
        console.log('promise2')
    })
}, 0)
浏览器输出:
time1
promise1
time2
promise2
Node输出:
time1
time2
promise1
promise2
在这个例子中,Node的逻辑如下:
最初timer1和timer2就在timers阶段中。开始时首先进入timers阶段,执行timer1的回调函数,打印timer1,并将promise1.then回调放入microtask队列,同样的步骤执行timer2,打印timer2;
至此,timer阶段执行结束,event loop进入下一个阶段之前,执行microtask队列的所有任务,依次打印promise1、promise2。
例子2
setImmediate(() => {
  console.log('timer1')
  Promise.resolve().then(function () {
    console.log('promise1')
  })
})
setTimeout(() => {
  console.log('timer2')
  Promise.resolve().then(function () {
    console.log('promise2')
  })
}, 0)
Node输出:
timer1               timer2
promise1    或者     promise2
timer2               timer1
promise2             promise1
按理说setTimeout(fn,0)应该比setImmediate(fn)快,应该只有第二种结果,为什么会出现两种结果呢?
这是因为Node 做不到0毫秒,最少也需要1毫秒。实际执行的时候,进入事件循环以后,有可能到了1毫秒,也可能还没到1毫秒,取决于系统当时的状况。如果没到1毫秒,那么 timers 阶段就会跳过,进入 check 阶段,先执行setImmediate的回调函数。
另外,如果已经过了Timer阶段,那么setImmediate会比setTimeout更快,例如:
const fs = require('fs');
fs.readFile('test.js', () => {
  setTimeout(() => console.log(1));
  setImmediate(() => console.log(2));
});
上面代码会先进入 I/O callbacks 阶段,然后是 check 阶段,最后才是 timers 阶段。因此,setImmediate才会早于setTimeout执行。
3不同异步任务执行的快慢
setTimeout(() => console.log(1));
setImmediate(() => console.log(2));
Promise.resolve().then(() => console.log(3));
process.nextTick(() => console.log(4));
输出结果:4 3 1 2或者4 3 2 1
因为我们上文说过microTask会优于macroTask运行,所以先输出下面两个,而在Node中process.nextTick比Promise更加优先[3],所以4在3前。而根据我们之前所说的Node没有绝对意义上的0ms,所以1,2的顺序不固定。
4MicroTask队列与MacroTask队列
   setTimeout(function () {
       console.log(1);
   },0);
   console.log(2);
   process.nextTick(() => {
       console.log(3);
   });
   new Promise(function (resolve, rejected) {
       console.log(4);
       resolve()
   }).then(res=>{
       console.log(5);
   })
   setImmediate(function () {
       console.log(6)
   })
   console.log('end');
Node输出:
2 4 end 3 5 1 6
这个例子来源于《JavaScript中的执行机制》。Promise的代码是同步代码,then和catch才是异步的,所以4要同步输出,然后Promise的then位于microTask中,优于其他位于macroTask队列中的任务,所以5会优于1,6输出,而Timer优于Check阶段,所以1,6。

nodejs,事件轮询总结的更多相关文章

  1. 12.nodejs事件轮询机制

    一:nodejs事件轮询机制  就是  函数的执行顺序 <script type="text/javascript"> setImmediate(function(){ ...

  2. nodejs事件轮询详述

    目录 概述 nodejs特点 事件轮询 关于异步方法 概述 关于nodejs的介绍网上资料非常多,最近由于在整理一些函数式编程的资料时,多次遇到nodejs有关的内容.所以就打算专门写一篇文章总结一下 ...

  3. 理解Node.js的事件轮询

    前言 总括 : 原文地址:理解Node.js的事件轮询 Node小应用:Node-sample 智者阅读群书,亦阅历人生 正文 Node.js的两个基本概念 Node.js的第一个基本概念就是I/O操 ...

  4. 面试题: nodejs 的事件轮询机制

    setTimeout(function(){ console.log('setTimeout()执行了') },0) setImmediate(function(){ console.log('set ...

  5. node.js事件轮询(1)

    事件轮询(引用) 事件轮询是node的核心内容.一个系统(或者说一个程序)中必须至少包含一个大的循环结构(我称之为"泵"),它是维持系统持续运行的前提.nodejs中一样包含这样的 ...

  6. 对Node.JS的事件轮询(Event Loop)的理解

    title: Node.JS的事件轮询(event loop)的理解 categories: 理解 tags: Node JS 机制 当我们知道I/O操作和创建新线程的开销是巨大的! 网站延迟的开销 ...

  7. Node.js的事件轮询Event Loop原理

    Node.js的事件轮询Event Loop原理解释 事件轮询主要是针对事件队列进行轮询,事件生产者将事件排队放入队列中,队列另外一端有一个线程称为事件消费者会不断查询队列中是否有事件,如果有事件,就 ...

  8. 理解JavaScript中的事件轮询

    原文:http://www.ruanyifeng.com/blog/2014/10/event-loop.html 为什么JavaScript是单线程 JavaScript语言的一大特点就是单线程,也 ...

  9. JS中的异步以及事件轮询机制

    一.JS为何是单线程的? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊.(在JAVA和c#中的异步 ...

随机推荐

  1. 前端每日实战:45# 视频演示如何用纯 CSS 创作一个菱形 loader 动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/eKzjqK 可交互视频教程 此视频 ...

  2. 批量去除输出数据文件名前面的"\output\“

    for file in \output\*; do mv "\(file" "\){file#\output\_}";done;

  3. Oracle12c修改时区

    Oacle12c支持可插入数据库(PDB)在一个统一的数据库(CDB)中具有不同的字符集.时区文件版本和数据库时区. 出于性能原因,Oracle建议将数据库时区设置为UTC(0:00),因为不需要转换 ...

  4. linux运维、架构之路-网络基础

    一. 常用网络设备 1.交换机:实现多台主机之间互相通讯的需求 交换机实现互相通讯的要求: ①主机身份标识信息:mac地址,利用源mac和目标mac地址,进行身份信息识别 ②主机通过交换机识别目标主机 ...

  5. Jira插件安装

    以下操作需要反编译 1.反编译的jar包 1)E:\JIRA安装路径\atlassian-jira\WEB-INF\atlassian-bundled-plugins\atlassian-univer ...

  6. spring boot 开静态资源访问,配置视图解析器

    配置视图解析器spring.mvc.view.prefix=/pages/spring.mvc.view.suffiix= spring boot 开静态资源访问application.proerti ...

  7. 如何Docker化任意一个应用

    网上有很多关于如何将应用Docker化的教程,为什么我还要再写一个呢? 我见过的大部分教程都是限定在某种特定技术(例如Java或者Python),可能无法满足读者的需求.同时,这些教程也没有说清楚关于 ...

  8. [CF-GYM]Abu Tahun Mod problem题解

    前言 这道题比较简单,但我还是想了好一会 题意简述 Abu Tahun很喜欢回文. 一个数组若是回文的,那么它从前往后读和从后往前读都是一样的,比如数组\(\left\{1\right\},\left ...

  9. 20180708-Java基本数据类型

    public class PrimitiveTypeTest{ public static void main(String[] args){ //byte System.out.println(&q ...

  10. VBox 启动虚拟机失败 - NtCreateFile(\Device\VBoxDrvStub)

    在Vbox(5.0.8 版本)启动Ubuntu的虚拟机时,遇到错误信息: NtCreateFile(\Device\VBoxDrvStub) failed: 0xc000000034 STATUS_O ...