一、定时器

  setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。

  需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。

二、Node.js的Event Loop

  Node.js也是单线程的Event Loop,但是它的运行机制不同于浏览器环境。

  除了setTimeout和setInterval这两个方法,Node.js还提供了另外两个与"任务队列"有关的方法:process.nextTick和setImmediate。它们可以帮助我们加深对"任务队列"的理解。

  process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。setImmediate方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像。请看下面的例子(via StackOverflow)。

  如果有多个process.nextTick语句(不管它们是否嵌套),将全部在当前"执行栈"执行。

  process.nextTick和setImmediate的一个重要区别:多个process.nextTick语句总是在当前"执行栈"一次执行完,多个setImmediate可能则需要多次loop才能执行完。事实上,这正是Node.js 10.0版添加setImmediate方法的原因,否则像下面这样的递归调用process.nextTick,将会没完没了,主线程根本不会去读取"事件队列"!

  另外,由于process.nextTick指定的回调函数是在本次"事件循环"触发,而setImmediate指定的是在下次"事件循环"触发,所以很显然,前者总是比后者发生得早,而且执行效率也高(因为不用检查"任务队列")。

三、Macrotasks和Microtasks

Macrotasks和Microtasks 都属于上述的异步任务中的一种,他们分别有如下API:
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering
microtasks: process.nextTick, Promise, MutationObserver

setTimeout的macrotask, 和 Promise的microtask 有哪些不同,先来看下代码如下:

console.log(1);
setTimeout(function(){
console.log(2);
}, 0);
Promise.resolve().then(function(){
console.log(3);
}).then(function(){
console.log(4);
}); //1
//3
//4
//2

   

  如上代码可以看到,Promise的函数代码的异步任务会优先于setTimeout的延时为0的任务先执行。

  原因是任务队列分为 macrotasks 和 microtasks, 而promise中的then方法的函数会被推入到microtasks队列中,而setTimeout函数会被推入到macrotasks任务队列中,在每一次事件循环中,macrotask只会提取一个执行,而microtask会一直提取,直到microsoft队列为空为止。

  也就是说如果某个microtask任务被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止。

  而事件循环每次只会入栈一个macrotask,主线程执行完成该任务后又会检查microtasks队列并完成里面的所有任务后再执行macrotask的任务。

定时器setTimeout()和Node.js的Event Loop的更多相关文章

  1. 浅析Node.js的Event Loop

    目录 浅析Node.js的Event Loop 引出问题 Node.js的基本架构 Libuv Event Loop Event Loop Phases Overview Poll Phase The ...

  2. 理解 Node.js 的 Event loop

    问题 考察如下代码,脑回路中运行并输出结果: console.log("1"); setTimeout(function setTimeout1() { console.log(& ...

  3. 【Node.js】Event Loop执行顺序详解

    本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...

  4. Node.js学习 - Event Loop

    Node.js本身是单线程,但通过事件和回调支持并发,所以性能非常高. Node.js的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. 事件驱动程序 实例 var ev ...

  5. JS的Event Loop

    JavaScript是单线程的,只有一个执行栈,一次只能做一件事. 在浏览器中,却“好像”可以同时做几件事:点击,发送请求,执行多个函数,解析代码. 这是因为浏览器实现的Event Loop机制. W ...

  6. 浏览器和Node 中的Event Loop

    前言 js与生俱来的就是单线程无阻塞的脚本语言. 作为单线程语言,js代码执行时都只有一个主线程执行任务. 无阻塞的实现依赖于我们要谈的事件循环.eventloop的规范是真的苦涩难懂,仅仅要理解的话 ...

  7. [Node.js] 04 - Event and Callback

    回调函数 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数. 异步读取文件的回调函数: var fs = require("fs&quo ...

  8. Js 运行机制和Event Loop

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

  9. JS event loop

    一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...

随机推荐

  1. 常见的HTTP状态码(HTTP Status Code)说明

    作为一个互联网开发人员对于一些服务器返回的HTTP状态的意思都必须是了如指掌的,只有将这些状态码一一弄清楚,工作中遇到的各种问题才能够处理的得心应手.好了,下面就让我们来了解一下比较常见的HTTP状态 ...

  2. 小程序中data数据的处理方法总结(小程序交流群:604788754)

    WXML: <view class="container"> <view wx:for="{{list}}" wx:key="thi ...

  3. greenplum中to_date函数注意点

    今天协助排查异常数据,发现是如下类似代码产生的: to_date(col_name,'yyyymmdd'),其中col_name是date类型. 这个代码运行后,结果是:2018-11-16的date ...

  4. APP压力稳定性测试之monkey入门

    1.什么是monkey? Monkey是一个命令行工具,使用安卓调试桥(adb)来运行它,模拟用户触摸屏幕.滑动Trackball.按键等随机事件流来对设备上的程序进行压力测试,检测程序多久的时间会发 ...

  5. java编写ID3决策树

    说明:每个样本都会装入Data样本对象,决策树生成算法接收的是一个Array<Data>样本列表,所以构建测试数据时也要符合格式,最后生成的决策树是树的根节点,通过里面提供的showTre ...

  6. Python标准库--time模块的详解

    time模块 - - -时间获取和转换 在我们学习time模块之前需要对以下的概念进行了解: 时间戳:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08 ...

  7. python 统计单词个数,并按个数与字母排序

    # coding: utf-8 # In[1]: import collections str = "Be slow to promise and quick to perform" ...

  8. jqgrid自定义列表开发=》实现高级查询

    标题已指出本文要说的三件事,首先是主角jqgrid,将应用在自定义列表中,重点介绍如何实现高级查询. 使用jqgrid实现自定义列表分为两大步骤,首先是要根据业务完成jqgrid的对象定义,即列表的描 ...

  9. 展示金额的方法(1元-->1.00元)

    public static String showMoneyByTwoDecimal(String account) { DecimalFormat doubleFormatter = new Dec ...

  10. Python的基础语法

    一,编码 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 当然你也可以为源码文件指定不同的编码: 1 # -*- coding: cp-1252 ...