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)事件对象
事件对象 • 什么是事件对象? • 就是当你触发了一个事件以后,对该事件的一些描述信息 • 例如: ° 你触发一个点击事件的时候,你点在哪个位置了,坐标是多少 ° 你触发一个键盘事件的时候,你按的是哪 ...
随机推荐
- linux 内存布局以及tlb更新的一些理解
问题: 1.内核线程是否有vma线性区? 2.单线程的一个进程,它修改了自己的页表,是否需要发送ipi来通知其他核更新tlb? 3.普通进程,在32位和64位,对应的线性区的最大地址能到多少? 在64 ...
- java.lang.ClassNotFoundException: org.hibernate.engine.SessionFactoryImplementor
Hibernate4.x与spring3.x整合,有关事务的处理,用Junit4测试,出现org.springframework.beans.factory.BeanCreationException ...
- Kubernetes 1.8.x 全手动安装教程----转自Kubernetes中文社区(部分内容根据实验环境做了些修改,特此感谢Kubernetes中文社区)
Kubernetes 提供了许多云端平台与操作系统的安装方式,本章将以全手动安装方式来部署,主要是学习与了解 Kubernetes 创建流程.若想要了解更多平台的部署可以参考 Picking the ...
- CentOS 7下源码安装zabbix服务
安装环境需要LAMP或者LNMP先搭建好 在此我使用上一篇搭建好的LNMP环境来安装zabbix 1.下载zabbix http://www.zabbix.com/download.php 2.安装及 ...
- Linux下MySQL5.7.18二进制包安装(手动添加配置文件my_default.cnf)
本文出处:http://www.cnblogs.com/wy123/p/6815049.html 最新在学习MySQL,纯新手,对Linux了解的也不多,因为是下载的最新版的MySQL(MySQL5. ...
- delphi 原创应用工具箱
用到的主要知识点: (1) listview背景透明 (2) 读取应用图标 (3)图标透明 (4)实时显示微软必应首页图,裁剪图片等
- jira-6.0.1-x64下载地址
http://downloads.atlassian.com/software/jira/downloads/atlassian-jira-6.0.1-x64.bin
- Kubernetes+Prometheus+Grafana部署笔记
一.基础概念 1.1 基础概念 Kubernetes(通常写成“k8s”)Kubernetes是Google开源的容器集群管理系统.其设计目标是在主机集群之间提供一个能够自动化部署.可拓展.应用容器可 ...
- you-get
1.打开cmd,输入命令并执行 pip3 install you-get 2.输入命令,检测 You-Get 是否安装成功 you-get 3.开始下载吧 you-get [视频地址]you-get ...
- 学JS的心路历程-函式(六)其余参数及预设参数
今天我们要来介绍ES6新增的其余参数及预设参数! 其余参数rest parameter …numbers可以让我们表示不确定数量的参数,并将其视为一个数组: function getVal(…numb ...