定时器setTimeout()和Node.js的Event Loop
一、定时器
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的更多相关文章
- 浅析Node.js的Event Loop
目录 浅析Node.js的Event Loop 引出问题 Node.js的基本架构 Libuv Event Loop Event Loop Phases Overview Poll Phase The ...
- 理解 Node.js 的 Event loop
问题 考察如下代码,脑回路中运行并输出结果: console.log("1"); setTimeout(function setTimeout1() { console.log(& ...
- 【Node.js】Event Loop执行顺序详解
本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...
- Node.js学习 - Event Loop
Node.js本身是单线程,但通过事件和回调支持并发,所以性能非常高. Node.js的每一个API都是异步的,并作为一个独立线程运行,使用异步函数调用,并处理并发. 事件驱动程序 实例 var ev ...
- JS的Event Loop
JavaScript是单线程的,只有一个执行栈,一次只能做一件事. 在浏览器中,却“好像”可以同时做几件事:点击,发送请求,执行多个函数,解析代码. 这是因为浏览器实现的Event Loop机制. W ...
- 浏览器和Node 中的Event Loop
前言 js与生俱来的就是单线程无阻塞的脚本语言. 作为单线程语言,js代码执行时都只有一个主线程执行任务. 无阻塞的实现依赖于我们要谈的事件循环.eventloop的规范是真的苦涩难懂,仅仅要理解的话 ...
- [Node.js] 04 - Event and Callback
回调函数 回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数. 异步读取文件的回调函数: var fs = require("fs&quo ...
- Js 运行机制和Event Loop
一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
- JS event loop
一.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
随机推荐
- 第七届 蓝桥杯 方格填数 dfs
如下的10个格子 填入0~9的数字.要求:连续的两个数字不能相邻. (左右.上下.对角都算相邻) 一共有多少种可能的填数方案? 请填写表示方案数目的整数. 注意:你提交的应该是一个整数,不要填写任何 ...
- django模型系统(二)
django模型系统(二) 常用查询 每一个django模型类,都有一个默认的管理器,objects QuerySet表示数据库中对象的列表.他可以有0到国歌过滤器.过滤器通过给定参数,缩小查询范围( ...
- vue-cli使用swiper插件
使用的教程https://blog.csdn.net/lbpro0412/article/details/82465067
- 使用Notepad++编译运行C/C++/Python程序
对我来说,比较常用的是C/C++/Python. 使用Notepad++编译运行单个源文件的C/C++/Python,比使用复杂的IDE更加快捷. 想要让Notepad++能够做到编译运行C/C++/ ...
- 【调试基础】Part 5 PE格式
PE概念.区块分类
- 路由导航之第一个子模块(HomeModule)
git clone git@github.com:len007/my-angular2-app.git my-angular2-app 开始 一个URL = 一个页面 = 一个Component. 我 ...
- sqlserver数据库方面的排序四大王
--1. row_number 用法 这个函数的功能是为查询出来的每一行记录生成一个序号select row_number() over(order by stuid) as row_number,* ...
- 微信浏览器无法下载APK文件的解决方案
大家是不是经常会遇到微信内点击链接或扫描二维码无法打开指定网页的问题?只要你使用微信转发分享,相信你就一定会遇到,那么打不开的原因很简单了,就是被微信拦截了.这个问题我们只需要实现从微信内直接跳出到外 ...
- ssh自动登入
公司的服务器在国外,所以测试的查看日志的时候需要测试机,然后继续ssh 非常不方便,所以编写一个简单的ssh登入脚本 #!/usr/bin/expectset timeout 3spawn ssh n ...
- sed 命令总结
sed是Stream Editor的缩写,是操作.过滤.转换文本内容的强大工具,对文件实现增删改查 主要参数 -n 取消默认输出 -i 修改保存文件 内置命令字符 a,append追加 d,delet ...