对于js任务队列的理解

  • 这篇文章是我本身的一个学习总结,并非很是详细,结合给出的连接能够有更细致的认识
  • 先介绍几个概念,便于理解

关于堆和栈(做为内存区域来讲)

  • 堆(heap):存放object、array、function等不肯定内存大小的数据存储;
  • 栈(stack):存放基本数据类型以及引用数据类型指向堆中的数据的指针,具备具体大小的数据结构,存取速度快;

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

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

事件循环机制(event loop)

参考:js事件循环机制javascript

  • 存在整个javascript脚本执行期间
  • 做用:将任务队列的中能够执行的函数压入调用栈中

任务队列(task queue)

任务队列主要分为两种:html

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

    宏任务主要包括:script(总体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
  2. 微任务(micro task):在新标准中叫jobsjava

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

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

执行特色:

  • 每当调用栈为空时,事件循环机制会将一个宏任务队列中任务压入调用栈中
  • 以空的调用栈为起点的话,先执行全部宏任务,再执行全部微任务,而后调用栈又为空,这样一次能够看做一个单元,以后就是一直在循环执行这样单元

分解执行过程:segmentfault

  1. 执行全部调用栈中的宏任务
  2. 宏任务执行过程当中产生的微任务加入到微任务队列
  3. 宏任务执行完马上执行全部微任务队列中的任务
  4. 以上执行完毕,检查渲染,GUI线程接管渲染
  5. 渲染完毕后,js线程接管,开启下一次事件循环(每一次事件循环(script不包括),只处理一个宏任务),执行下一次宏任务(任务队列中取)

很差理解的地方浏览器

  • 以上过程(不管宏任务仍是微任务执行)中产生的宏任务进入宏任务队列等待,进入后面的循环执行,不在当次循环中被执行
  • 可是以上过程当中(包括微任务)产生的微任务又会被马上放到当次循环的微任务队列后面按顺序执行

以上两句可能有点绕,能够参考上面循环机制的连接,有相关图解。数据结构

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

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

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
相关文章
相关标签/搜索