资讯专栏INFORMATION COLUMN

对于js任务队列的理解

piapia / 2993人阅读

摘要:换个说法微任务优先于当前调用栈产生的宏任务被执行如果能理解下面这段代码的执行过程应该就基本理解任务队列的执行过程了输出顺序为,,,,,,

这篇文章是我自己的一个学习总结,并不是非常详细,结合给出的链接可以有更细致的认识

先介绍几个概念,便于理解

关于堆和栈(作为内存区域来说)

堆(heap):存放object、array、function等不确定内存大小的数据存储;

栈(stack):存放基本数据类型以及引用数据类型指向堆中的数据的指针,具有具体大小的数据结构,存取速度快;

调用栈(作为一种代码运行机制)

call stack(调用栈)指的是函数调用运行的机制,具体参考该链接:javascrip调用栈

事件循环机制(event loop)

参考:js事件循环机制

存在整个javascript脚本执行期间

作用:将任务队列的中可以执行的函数压入调用栈中

任务队列(task queue)

任务队列主要分为两种:

宏任务(macro task):在新标准中叫task

宏任务主要包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering

微任务(micro task):在新标准中叫jobs

微任务主要包括:process.nextTick, Promise, Object.observe(已废弃), MutationObserver(html5新特性)

以上提到的不只有浏览器方法,还有nodejs的方法,这里不具体说明了

执行特点:

每当调用栈为空时,事件循环机制会将一个宏任务队列中任务压入调用栈中

以空的调用栈为起点的话,先执行所有宏任务,再执行所有微任务,然后调用栈又为空,这样一次可以看作一个单元,之后就是一直在循环执行这样单元

分解执行过程:

执行所有调用栈中的宏任务

宏任务执行过程中产生的微任务加入到微任务队列

宏任务执行完立刻执行所有微任务队列中的任务

以上执行完毕,检查渲染,GUI线程接管渲染

渲染完毕后,js线程接管,开启下一次事件循环(每一次事件循环(script不包括),只处理一个宏任务),执行下一次宏任务(任务队列中取)

不好理解的地方

以上过程(无论宏任务还是微任务执行)中产生的宏任务进入宏任务队列等待,进入后面的循环执行,不在当次循环中被执行

但是以上过程中(包括微任务)产生的微任务又会被立刻放到当次循环的微任务队列后面按顺序执行

以上两句可能有点绕,可以参考上面循环机制的链接,有相关图解。

换个说法:微任务优先于当前调用栈产生的宏任务被执行

如果能理解下面这段代码的执行过程应该就基本理解任务队列的执行过程了:

setTimeout(() => {
    console.log("1")

    new Promise((resolve) => {
        resolve()
    }).then(() => {
        console.log("2")
    })
}, 0);

setTimeout(() => {
    console.log("3")
}, 0);

new Promise((resolve) => {
    resolve()
}).then(() => {
    console.log("4")

    new Promise((resolve) => {
        resolve()
    }).then(() => {
        console.log("5")
    })

    setTimeout(() => {
        console.log("6")
    }, 0);
})

new Promise((resolve) => {
    resolve()
}).then(() => {
    console.log("7")
})

// 输出顺序为: 4,7,5,1,2,3,6

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97486.html

相关文章

  • JavaScript 运行机制详解(理解同步、异步和事件循环)

    摘要:从异步过程的角度看,函数就是异步过程的发起函数,事件监听函数就是异步过程的回调函数。事件触发时,表示异步任务完成,会将事件监听器函数封装成一条消息放到消息队列中,等待主线程执行。 1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。JavaScrip...

    loonggg 评论0 收藏0
  • js事件循环机制(浏览器端Event Loop) 以及async/await理解

    摘要:接下来处理微任务队列,打印,后面一个不会有任何打印,但是会执行执行后面的代码打印进入第二次事件循环,执行宏任务队列打印 事件循环机制 理解js的事件循环机制,能够很大程度的帮我们更深层次的理解平时遇到的一些很疑惑的问题 简单版本 下面来看一段代码,想想它的结果和你的结果是否一样 setTimeout(function() { console.log(1) ...

    CKJOKER 评论0 收藏0
  • 【笔记】 你不知道JS读书笔记——异步

    摘要:异步请求线程在在连接后是通过浏览器新开一个线程请求将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件循环队列中。 基础:浏览器 -- 多进程,每个tab页独立一个浏览器渲染进程(浏览器内核) 每个浏览器渲染进程是多线程的,主要包括:GUI渲染线程 JS引擎线程 也称为JS内核,负责处理Javascript脚本程序。(例如V8引擎) JS引擎线程负...

    junnplus 评论0 收藏0
  • 【转】深入理解JS单线程机制【原文作者:MasterYao】

    摘要:的单线程,与它的用途有关。只要指定过回调函数,这些事件发生时就会进入任务队列,等待主线程读取。四主线程从任务队列中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为事件循环。令人困惑的是,文档中称,指定的回调函数,总是排在前面。 原文:http://www.cnblogs.com/Master... 一、为什么JavaScript是单线程? JavaScript语言的一大特点...

    LittleLiByte 评论0 收藏0
  • 今天,我明白了JS事件循环机制

    摘要:而这些队列由的事件循环来搞定宏任务与微任务,在最新标准中,它们被分别称为与。我们梳理一下事件循环的执行机制循环首先从宏任务开始,遇到,生成执行上下文,开始进入执行栈,可执行代码入栈,依次执行代码,调用完成出栈。 写在前面 js是一门单线程的编程语言,也就是说js在处理任务的时候,所有任务只能在一个线程上排队被执行,那如果某一个任务耗时比较长呢?总不能等到它执行结束再去执行下一个。所以在...

    maochunguang 评论0 收藏0

发表评论

0条评论

piapia

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<