js 异步、栈、事件循环、任务队列

在开发中经常遇到js的异步问题,为了方便理解,记录下来,随时回顾。

  • 以下的所有代码都是在浏览器环境下运行

在浏览器中js的运行是依赖浏览器js引擎来解析的,并且是在一定的runtime(运行时)的环境被调用,被执行。由于js引擎是单线程的,所以在执行dom渲染,script引入的时候这些操作是同步的,js引擎会通过 Event Loop 的机制,按顺序把任务放入栈中执行

而在代码中产生的异步代码则是由 runtime 提供的,拥有和Js引擎互不干扰的线程

栈是一个后进先出的一种数据结构,执行起来效率比较高,往往堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针,在函数调用的时候,会产生函数的执行栈,也叫执行上下文,这个执行环境中存在着这个函数的私有作用域,上层作用域的指向,函数的参数,这个作用域中定义的变量以及这个作用域的this对象。 而当一系列函数被依次调用的时候,因为js是单线程的,同一时间只能执行一个函数,于是这些函数被排队在一个单独的地方。这个地方被称为执行栈。

当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。。这个过程反复进行,直到执行栈中的代码全部执行完毕。

总的来说

  • 栈存放着一些基础类型变量以及对象的指针
  • 当代码执行的时候,同步代码按照执行顺序开始执行
  • 当代码执行的时候,碰到函数,引擎会在栈里产生这个函数执行栈,也叫执行上下文。
  • 当代码执行到函数的时候,会进入这个执行环境继续执行其中的代码,反复进行,全部执行完

任务队列

Js 中,有两类任务队列:宏任务队列(macro tasks)和微任务队列(micro tasks)。宏任务队列可以有多个,微任务队列只有一个
  • 宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.
  • 微任务:process.nextTick (node.js中进程相关的对象), Promise, Object.observer, MutationObserver。

在浏览器的 Event Loop机制中,整个流程可以用张图来表示一下:

这张图中可以看到:

  • 微任务队列(micro tasks)只会有一个
  • 宏任务队列(macro tasks)可以有多个
  • click ajax 等回调方法都会进入到宏任务队列(macro tasks)中,当然也包括上面的

而在浏览器的Event Loop机制运行时,宏任务队列(macro tasks)和微任务队列(micro tasks)的关系,关于这点详见(关系

  • 宏任务按顺序执行,且浏览器在每个宏任务之间渲染页面
  • 所有微任务也按顺序执行,且在以下场景会立即执行所有微任务
    • 每个回调之后且js执行栈中为空。
    • 每个宏任务结束后。

而在 NodeJs 的 Event Loop 遵循的是 libuv

这个库是node作者自己写的,内部实现了一整套的异步io机制(内部使用c++和js实现),使我们开发异步程序变得简单,因为这个原因导致了一些js解析和浏览器的会不一样。

NodeJs 的运行是这样的:

  • 初始化 Event Loop
  • 执行您的主代码。这里同样,遇到异步处理,就会分配给对应的队列。直到主代码执行完毕。
  • 执行主代码中出现的所有微任务:先执行完所有nextTick(),然后在执行其它所有微任务。
  • 开始 Event Loop

当每个阶段执行完毕后,都会执行所有微任务(先 nextTick,后其它),然后再进入下一个阶段。

最后我们来段代码彻底解析下两类任务队列在运行时的逻辑

console.log('1');

setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
}) setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})

结合上面讲的逻辑 可以分析一波得出最后答案是1,7,6,8,2,4,3,5,9,11,10,12

js的事件循环和任务队列的更多相关文章

  1. JS 的线程、事件循环、任务队列简介

    JS 是单线程的,但是却能执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和任务队列(Task Queue). 事件循环:JS 会创建一个类似于 while (true) 的循 ...

  2. JS 事件循环机制 - 任务队列、web API、JS主线程的相互协同

    一.JS单线程.异步.同步概念 从上一篇说明vue nextTick的文章中,多次出现“事件循环”这个名词,简单说明了事件循环的步骤,以便理解nextTick的运行时机,这篇文章将更为详细的分析下事件 ...

  3. JS JavaScript事件循环机制

    区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...

  4. JS-线程、事件循环、任务队列

    JS 是单线程的,但是却能执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和任务队列(Task Queue). 事件循环: JS 会创建一个类似于 while (true) 的 ...

  5. 浏览器中 JS 的事件循环机制

    目录 事件循环机制 宏任务与微任务 实例分析 参考 1.事件循环机制 浏览器执行JS代码大致可以分为三个步骤,而这三个步骤的往复构成了JS的事件循环机制(如图). 第一步:主线程(JS引擎线程)中执行 ...

  6. js的事件循环绑定和jQuery的隐式迭代

    js的事件循环绑定和jQuery的隐式迭代 js事件循环绑定 jQuery隐式迭代 先举一个例子:给定一个ul,点击列表内的每一个li元素,使它的背景色变红,下边分别用js代码和jQuery实现. & ...

  7. Node.js:事件循环

    ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...

  8. Node.js 的事件循环机制

    目录 微任务 事件循环机制 setImmediate.setTimeout/setInterval 和 process.nextTick 执行时机对比 实例分析 参考 1.微任务 在谈论Node的事件 ...

  9. JS:事件循环机制、调用栈以及任务队列

    点击查看原文 写在前面 js里的事件循环机制十分有趣.从很多面试题也可以看出来,考察简单的setTimeout也就是考察这个机制的. 在之前,我只是简单地认为由于函数执行很快,setTimeout执行 ...

随机推荐

  1. js冒泡排序和数组去重

    1.冒泡排序 <script>//声明一个数组 var arr=[1,88,66,22,35,65,4,52];//自执行函数 (function maopao(){ for(var i= ...

  2. scrapy分布式浅谈+京东示例

    scrapy分布式浅谈+京东示例: 学习目标: 分布式概念与使用场景 浅谈去重 浅谈断点续爬 分布式爬虫编写流程 基于scrapy_redis的分布式爬虫(阳关院务与京东图书案例) 环境准备: 下载r ...

  3. mysql 格式化保存

    win -e 'SELECT * from t_share_template;' | sed 's/\t/,/g' > aa.csv

  4. Javascript 模块化概述

    模块化的目的 当网站开发得越来越复杂,会经常遇到以下问题: 命名冲突 文件依赖 Sea.js 一个适合web前端的模块加载器,遵守 CMD (Common Module Definition)模块定义 ...

  5. 5073 [Lydsy1710月赛]小A的咒语

    LINK:[Lydsy1710月赛]小A的咒语 每次给定两个串 要求从a串中选出x段拼成B串 能否做到.T组数据. \(n\leq 100000,m\leq 100000,T\leq 10,x\leq ...

  6. IEnumerable<T>转DataTable,为空怎么办?

    public static class DataConvertor { public static DataTable ToDataTable<T>(IEnumerable<T> ...

  7. 大话Android中的Handler机制

    在Android的线程间通信中,Handler独当一面,无论是framework层还是app层中都出现的相当频繁,有必要好好的拿出来深挖一下它的实现原理.而要说Handler的通信机制,除了Handl ...

  8. Python安装2 —— Pycharm2019.3.3的安装

    本文内容皆为作者原创,如需转载,请注明出处:https://www.cnblogs.com/xuexianqi/p/12378617.html 一:什么是Pycharm PyCharm是一种Pytho ...

  9. 当asp.net core偶遇docker一(模型验证和Rabbitmq 二)

    上一篇我们说到构建了一个Rabbitmq容器 现在我们说说如何在一个悄悄传输消息到队列 我们现在设计一个Rabbitmq发送消息部分的模块 先设计一个远程发送的接口 public interface ...

  10. 职场老鸟,一文教你如何正确入门Python爬虫!

    爬虫现在的火热程度我就不说了,先说一下这门技术能干什么事儿,主要为以下三方面: 1.爬取数据,进行市场调研和商业分析 爬取知乎.豆瓣等网站的优质话题内容:抓取房产网站买卖信息,分析房价变化趋势.做不同 ...