node.js中对Event Loop事件循环的理解
javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务。
同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行。
异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行。
任务的运行机制如下:
1、所有同步任务在主线程上执行,形成一个 "执行栈",注意栈是先进后出的。
2、主线程外,有一个 "任务队列" ,只要异步任务处理完有结果了,就在 "任务队列" 中放置一个事件,注意队列是先进先出的。
3、一旦 "执行栈" 中所有同步任务执行完毕。系统读取 "任务队列" 中的事件,对应的异步任务。放入 "执行栈" 中,开始执行。
4、主线程不断重复第三步,这种循环从 "任务队列" 中读取事件处理的这种运行机制称为Event Loop(事件循环)。
"执行栈" 中的同步代码总是比 "任务队列"中的异步任务之前运行。
function fun() {
setTimeout(function () {
console.log('异步任务');
}, 0);
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
}
fun();
上面的代码,console.log代码写在setTimeout后面,但仍然先执行。
"任务队列" 是一个队列,队列的特性是先进先出。看下面代码:
function fun() {
console.log(1);
setTimeout(function () {
console.log(2);
setTimeout(function () {
console.log(3);
}, 0);
}, 0);
console.log(4);
}
fun();
输出结果为 1 4 2 3,打印 2 的setTimeout任务比打印 3 的setTimeout任务先进入队列,所以会先运行。
对于异步操作,像ajax,只有操作成功后返回结果,才会进入 "任务队列" 中,而不是调用的时候就放入队列中。看下面代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
function ajax() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://mail.163.com/', true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
}
function fun() {
console.log(1);
ajax();
setTimeout(function () {
console.log(2);
}, 1000);
console.log(3);
}
fun();
</script>
</body>
</html>
ajax() 与 setTimeout 谁先进入队列,谁先输出,是需要看两者消耗时间,谁更短。时间短的会先进入队列先运行。
setTimeout 与 setInterval 运行机制一样,都是在指定时间把事件插入到 "任务队列" 尾部。区别是前者只执行一次,后者可反复执行。
node.js 还为我们提供了,process.nextTick 和 setImmediate 与 "任务队列" 有关的方法。
process.nextTick 会把回调函数放在当前 "执行栈" 的尾部。也就是说是在读取 "任务队列" 之前运行。
function fun() {
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
process.nextTick(function () {
console.log(3);
process.nextTick(function () {
console.log(4);
});
});
process.nextTick(function () {
console.log(5);
});
console.log(6);
}
fun();
上面的代码会输出 1 6 3 5 4 2 ,注意process.nextTick会把回调函数放在 "执行栈" 的尾部。
同步代码最先输出 1 6,然后 3 的先放入尾部,然后 5 的跟在 3 后面。3先执行,然后把 4 放入到 5 的后面。5执行完后,再执行4,最后读取 "任务队列" 中的输出2。
setImmediate 会把回调函数放在当前 "任务队列" 的尾部。也就是下一次事件循环Event Loop时执行。
function fun() {
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
setImmediate(function () {
console.log(3);
});
console.log(4);
}
fun();
上面的代码是会输出 1 4 2 3 还是 1 4 3 2 是不确定的,因为setTimeout 与 setImmediate 都会在下一次事件循环Event Loop中触发,所以输出是不确定的。
node.js中对Event Loop事件循环的理解的更多相关文章
- 为什么JS是单线程?JS中的Event Loop(事件循环)?JS如何实现异步?setimeout?
https://segmentfault.com/a/1190000012806637 https://www.jianshu.com/p/93d756db8c81 首先,请牢记2点: (1) JS是 ...
- Event Loop事件循环,GET!
JS中比较让人头疼的问题之一要算异步事件了,比如我们经常要等后台返回数据后进行dom操作,又比如我们要设置一个定时器完成特定的要求.在这些同步与异步事件里,异步事件肯定是在同步事件之后的,但是异步事件 ...
- javascript的event loop事件循环
javascript的event loop事件循环 这是今天一个朋友发给我的一个面试题, 感觉还挺有意思的, 写个博客以供分享 先看看这个面试题目: 观察下面的代码,写出输出结果 console.lo ...
- js event loop事件循环
浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...
- 浅谈 Event loop (事件循环)
从Event Loop谈JS的运行机制 先来理解一个概念: JS分为同步任务和异步任务 同步任务都在主线程上执行,形成一个执行栈 Execute Content Stack 主线程之外,事件触发线程管 ...
- 进程,线程,Event Loop(事件循环),Web Worker
线程,是程序执行流的最小单位.线程可与同属一个进程的其他线程共享所拥有的全部资源,同一进程中的多个线程之间可以并发执行.线程有就绪,阻塞,运行三种基本状态. 阮一峰大神针对进程和线程的类比,很是形象: ...
- JavaScript event loop事件循环 macrotask与microtask
macrotask 姑且称为宏任务,在很多上下文也被简称为task.例如: setTimeout, setInterval, setImmediate, I/O, UI rendering. mic ...
- [Node.js] Use nodejs-dashboard event loop delay with hrtime()
In this lesson, you will learn how to use the Formidable nodejs-dashboard event loop delay to identi ...
- js中(event)事件对象
事件对象 • 什么是事件对象? • 就是当你触发了一个事件以后,对该事件的一些描述信息 • 例如: ° 你触发一个点击事件的时候,你点在哪个位置了,坐标是多少 ° 你触发一个键盘事件的时候,你按的是哪 ...
随机推荐
- UNITY 多个子MESH与贴图的对应关系
多个贴图时,与子MESH一一对应,如果多了 ...还待研究如何对应
- Open Tools API :IDE Main Menus
http://www.davidghoyle.co.uk/WordPress/?p=777 http://www.davidghoyle.co.uk/WordPress/?page_id=1110 h ...
- linux网卡桥接问题与docker网卡桥接问题
一.linux网卡桥接问题 在linux上创建桥接网卡,与真实的物理网卡进行绑定,相当于在linux中创建了一个虚拟的交换机,以linux网卡地址为源地址的数据,从桥接网卡br0进入,从实际的物理网卡 ...
- 吴裕雄 30-MySQL 及 SQL 注入
如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL注入安全的问题.本章节将为大家介绍如何防止SQL注入,并通过脚本来过滤SQL中注入的字符.所谓SQL注入,就是通过 ...
- linux配置虚拟主机
linux 下怎么配置虚拟主机 linux 下怎么配置虚拟主机,在网上找到N个资料都是高手们随便说几句,都没怎么说清楚.问题: 我把域名(bs.jxiop.com)指向了 68.10.140.10 ...
- lcd 控制器
1. 使用lcd 一般需要一个控制器和驱动器,控制器需要初始化以产生正确的时序,驱动器一般是和lcd基板制作在一起. LCD 控制器结构图: REGBANK 表示调色板 LCDDMA 表示DMA通道 ...
- k8s 调度器
https://blog.csdn.net/qq_21816375/article/details/78209605
- crontab -e文件存放路径
crontab -e结果存放在/var/spool/cron/crontabs中
- Parallax Mapping
[Parallax Mapping] Parallax mapping belongs to the family of displacement mapping techniques that di ...
- GraphicsTier
[GraphicsTier] 1.enum GraphicsTier 2.enum ShaderQuality 3.enum BuildTargetGroup 4.EditorGraphicsSett ...