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 只有一个线程,称之为主线程。而事件循环是主线程中执行栈里的代码执行完毕之后,才开始执行的。所以,主线程中要执行的代码时间过长,会阻塞事件循环的执行,也就会阻塞异步操作的执行。只有当主线程中执行栈为空的时候(即同步代码执行完后),才会进行事件循环来观察要执行的事件回调,当事件循环检测到任务队列中有事件就取出相关回调放入执行栈中由主线程执行。
例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);
Update:
《你不知道的 JavaScript》一书中,重新讲解了 ES6 新增的任务队列,和上面的任务队列略有不同,上面的任务队列书中称为事件队列。
上面提到的任务(事件)队列是在事件循环中的,事件循环每一次 tick 便执行上面所述的任务(事件)队列中的一个任务。而任务(事件)队列是只能往尾部添加任务。
而 ES6 中新增的任务队列是在事件循环之上的,事件循环每次 tick 后会查看 ES6 的任务队列中是否有任务要执行,也就是 ES6 的任务队列比事件循环中的任务(事件)队列优先级更高。
如 Promise 就使用了 ES6 的任务队列特性。
参考:
http://www.cnblogs.com/Medeor/p/4945687.html
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
http://www.cnblogs.com/zhaodongyu/p/3922961.html
深入浅出 node.js
JS 的线程、事件循环、任务队列简介的更多相关文章
- JS 单线程和事件循环
Js 是单线程,js代码从上到下依次执行,比如我们写了两个函数,肯定是上面的函数先执行,下面的函数后执行.但是这种单线程有一个非常大的问题,那就是遇到耗时的任务,后面的任务只能等待它执行完,才能进行. ...
- js异步、事件循环(EventLoop)小结
单线程 众所周知,JS是单线程的语言,之所以是单线程,用一句烂大街的话就是,如果两个线程同时操作一个DOM节点,那么该以哪个为准呢,虽然多线程也有办法解决,但是js毕竟是浏览器脚本语言,不需要那么复杂 ...
- JS执行机制--事件循环--笔记
JS的解析是由浏览器中的JS解析引擎完成的.JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始.但是又存在某些任务比较耗时,如IO读写等, ...
- js高级-浏览器事件循环机制Event Loop
JavaScript 是队列的形式一个个执行的 同一时间只能执行一段代码,单线程的 (队列的数据结构) 浏览器是多线程的 JavaScript执行线程负责执行js代码 UI线程负责UI展示的 Jav ...
- js 队列和事件循环
1.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UT ...
- js event loop事件循环
浏览器环境 以下两段代码是等价的.req对事件的回调设置,实际上就是当前主线程任务队列的任务. var req = new XMLHttpRequest(); req.open('GET', url) ...
- 破阵九解:Node和浏览器之事件循环/任务队列/异步顺序/数据结构
前言 本文内容比较长,请见谅.如有评议,还请评论区指点,谢谢大家! >> 目录 开门见山:Node和浏览器的异步执行顺序问题 两种环境下的宏任务和微任务(macrotask &&a ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
[摘要] 官网博文翻译,nodejs中的定时器 示例代码托管在:http://www.github.com/dashnowords/blogs 原文地址:https://nodejs.org/en/d ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...
- JS高阶---事件循环模式(事件轮询)
大纲: 相关知识点: 主体: (1)模型原理 JS部分:初始化代码执行 WebAPIS:执行上下文对象(不是一个真的对象,而是一个抽象的虚拟对象,可以看做栈里的一个区域,包含很多对象) setTime ...
随机推荐
- IE和火狐 差异
1.JavaScript中 1)IE和FireFox中childNodes的差别: <head> <script type="text/javascript"&g ...
- PHPSESSID的cookie
如果PHP脚本中有: 1 session_start(); 则说明使用了SESSION. SESSION是一种机制,可以在服务器端跨文件暂时保存数据或传递数据,常用于购物车等方面. SESSION只在 ...
- Xcode如何查看内存中的数据
在 debug 模式下如何在断点处,查看字符指针变量内存中的值,像vs2008的调试工具一样的内存查看器,现在只能查看第一个内存中的值可以在输出窗口采用gdb命令:x /nfu <addr&g ...
- (转)HTML5 本地存储
原文:http://www.cnblogs.com/rainman/archive/2011/06/22/2086069.html HTML5 本地存储 1.sessionStorage 2.loca ...
- ICTCLAS50中文分词软件“Init ICTCLAS failed!”问题
if (!ICTCLAS_Init(Server.MapPath("ICTCLAS50"))) { Response.Write( ...
- 安装VMware Tools找不到内核头文件
http://blog.csdn.net/bobbat/article/details/38568885 安装VMware Tools,解决无法找到kernel header path的问题 安装 V ...
- phpstom 实用laravel 需要附加的 命令
首先利用composer 下载相关的插件 在根目录执行此代码 composer require barryvdh/laravel-ide-helper 再者在config/app.php 添加一条命令 ...
- VBS_For_next
指定循环次数,使用计数器重复运行语句,语法结构如下: 1 2 3 4 5 For counter = start To end [Step step] [statements] [Ex ...
- UINavigationController的使用(多视图控制器)
一,重点 当视图控制器控制多视图时,所有页都有导航栏,如果我们有的页面不希望有导航栏咋办?网上没有搜索到结果,我探索到之后发表于此: [super navigationController].navi ...
- Selenium Grid原理
转载: http://blog.csdn.net/five3/article/details/9428655 Selenium-Grid版本 selenium-grid分为版本1和版本2,其实它的2个 ...