JS-线程、事件循环、任务队列
JS 是单线程的,但是却能执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和任务队列(Task Queue)。
事件循环:
JS 会创建一个类似于 while (true) 的循环,每执行一次循环体的过程称之为 Tick。每次 Tick 的过程就是查看是否有待处理事件,如果有则取出相关事件及回调函数放入执行栈中由主线程执行。待处理的事件会存储在一个任务队列中,也就是每次 Tick 会查看任务队列中是否有需要执行的任务。
任务队列:
异步操作会将相关回调添加到任务队列中。而不同的异步操作添加到任务队列的时机也不同,如 onclick, setTimeout, ajax 处理的方式都不同,这些异步操作是由浏览器内核的 webcore 来执行的,webcore 包含上图中的 3 种 webAPI,分别是 DOM Binding、network、timer 模块。
- onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任务队列中。
- setTimeout 会由浏览器内核的 timer 模块来进行延时处理,当时间到达的时候,才会将回调函数添加到任务队列中。
- ajax 则会由浏览器内核的 network 模块来处理,在网络请求完成返回之后,才将回调添加到任务队列中。
主线程
JS 只有一个线程,称之为主线程。而事件循环是主线程中执行栈里的代码执行完毕之后,才开始执行的。所以,主线程中要执行的代码时间过长,会阻塞事件循环的执行,也就会阻塞异步操作的执行。只有当主线程中执行栈为空的时候(即同步代码执行完后),才会进行事件循环来观察要执行的事件回调,当事件循环检测到任务队列中有事件就取出相关回调放入执行栈中由主线程执行。
- (所有代码都主线程里跑,主线程没代码了就在任务队列中读回调函数(异步操作)回到主线程里跑)
- 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
- 主线程之外,还存在一个 "任务队列"(task queue)。只要异步任务有了运行结果,就在 "任务队列" 之中放置一个事件。
- 一旦 "执行栈" 中的所有同步任务执行完毕,系统就会读取 "任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。("任务队列" 是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。)
例1:
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function (){}; // 这两个异步方法就会在 ajax 完成后推入任务队列,再由主线程执行
req.onerror = function (){};
req.send();例2:
setTimeout(function(){
// 如果有大量的操作,可能会阻塞 UI 等,则可以使用 setTimeout 让这些操作在主线程把更重要的代码执行完毕之后,再来执行这里的操作。从而提高浏览器的性能。
},0);// 设置为 0,也会有个最小间隔值,也会在主线程中的代码运行完成后,由事件循环从任务队列将回调添加到执行栈中才执行例3:
// 事件循环测试。执行结果是 2-3-4-1,1在最后输出,说明事件循环是所有同步代码执行完后才开始执行的。'use strict';
setTimeout(function() {
console.log(1);
}, 0);console.log(2);
let end = Date.now() + 1000*5;
while (Date.now() < end) {
}console.log(3);
end = Date.now() + 1000*5;
while (Date.now() < end) {
}console.log(4);
JS-线程、事件循环、任务队列的更多相关文章
- JS JavaScript事件循环机制
区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...
- 浏览器中 JS 的事件循环机制
目录 事件循环机制 宏任务与微任务 实例分析 参考 1.事件循环机制 浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图). 第一步:主线程(JS引擎线程)中执行 ...
- Node.js:事件循环
ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...
- Node.js 的事件循环机制
目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...
- js的事件循环绑定和jQuery的隐式迭代
js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...
- js的事件循环和任务队列
js 异步.栈.事件循环.任务队列 在开发中经常遇到js的异步问题,为了方便理解,记录下来,随时回顾. 以下的所有代码都是在浏览器环境下运行 在浏览器中js的运行是依赖浏览器js引擎来解析的,并且是在 ...
- JS:事件循环机制、调用栈以及任务队列
点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...
- js的事件循环机制和任务队列
上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别代表主线程中的任务和任务队列中的任务,那么此篇我们就来详细探讨这两者. 一.来张图感受一下 如果看完觉得一脸懵逼,请继续往 ...
- js的事件循环机制:同步与异步任务(setTimeout,setInterval)宏任务,微任务(Promise,process.nextTick)
javascript是单线程,一切javascript版的"多线程"都是用单线程模拟出来的,通过事件循环(event loop)实现的异步. javascript事件循环 事件循环 ...
- JavaScript之JS单线程|事件循环|事件队列|执行栈
本博文基于知乎"JavaScript作用域问题?"一问,而引起了对JavaScript事件循环和单线程等概念与实践上的研究.深入理解. 一.概念 0.关键词:JavaScript单 ...
随机推荐
- XmlNode.PrependChild 方法
using System; using System.IO; using System.Xml; public class Sample { public static void Main() { X ...
- Java日志使用slf4j 配置log4j后,有日志文件 但日志文件内容为空
SLF4J的全称是Simple Logging Facade for Java,即简单日志门面. SLF4J并不是具体的日志框架,而是作为一个简单门面服务于各类日志框架,如java.util.logg ...
- 数据映射-LSM Tree和SSTable
Coming from http://blog.sina.com.cn/s/blog_693f08470101njc7.html 今天来聊聊lsm tree,它的全称是log structured m ...
- 剑指Offer编程题(Java实现)——二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- loading 加载工具
loading 加载工具:http://loading.awesomes.cn/
- sobel算法的Soc FPGA实现之框架分析(二)
重点分析一.AXI_VDMA_1 之前一直认为这个就是内含有DDR的ip核(......最近才搞懂是个啥),后来经过对FDMA的分析发现这就是个框架,通AXI总线挂载到bus总线,可以实现PL端FPG ...
- C#将MD5后的字符串转为字符数据,随机大小写
一如下代码 public static string GenerateCode(Guid id, DateTime endTime, string Type) { string str = id + ...
- 阿里开源框架-JarsLink-【JAVA的模块化开发框架】
JarsLink (原名Titan) 是一个基于JAVA的模块化开发框架,它提供在运行时动态加载模块(一个JAR包).卸载模块和模块间调用的API. 需求背景 应用拆分的多或少都有问题.多则维护成本高 ...
- 关于使用itext转Html为pdf添加css样式的问题
使用的jar文件 xmlworker-5.5.11.jar itextpdf-5.5.11.jar 下载地址:https://pan.baidu.com/s/1i5AIBvZ 以下为测试代码 pack ...
- Centos7 配置rsyslog客户端接收远程日志
rsyslog 因为路由器我设定每天重启,但是日志一重启就会清除,并且路由器最多只能保存1024条记录,所以我想把路由器的日志记录到一台服务器上,发现路由器包含远程日志功能 于是我就在我的centos ...