微任务,宏任务顺序

Posted yf-html

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微任务,宏任务顺序相关的知识,希望对你有一定的参考价值。

前言

JS中整个循环当中,仅存在一个《》

理解一下概念问题 微任务,宏任务

 

宏任务需要多次事件循环才能执行完,微任务是一次性执行完的;

 

2.宏任务macrotask:

(事件队列中的每一个事件都是一个macrotask)

优先级:主代码块 > setImmediate > MessageChannel > setTimeout / setInterval

比如:setImmediate指定的回调函数,总是排在setTimeout前面

 

3.微任务包括:

优先级:process.nextTick > Promise > MutationObserver

 

需要多注意  process.nextTick 永远大于 promise.then,

原因其实很简单

 

在Node中,_tickCallback在每一次执行完TaskQueue中的一个任务后被调用,而这个_tickCallback中实质上干了两件事:

1.nextTickQueue中所有任务执行掉(长度最大1e4,Node版本v6.9.1)

2.第一步执行完后执行_runMicrotasks函数,执行microtask中的部分(promise.then注册的回调)

盗一张图:

技术图片

 

但是js异步有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入eventqueue,然后在执行微任务,将微任务放入eventqueue,

这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回掉函数,然后再从宏任务的queue上拿宏任务的回掉函数。 

 

 

 

技术图片

 

 

 

这张图可以看出:

  1. 存在微任务的话,那么就执行所有的微任务
  2. 微任务都执行完之后,执行第一个宏任务,
  3. 循环 1, 2

 這樣 可以总结一下如何分析异步执行的顺序:
首先我们分析有多少个宏任务;
在每个宏任务中,分析有多少个微任务;
根据调用次序,确定宏任务中的微任务执行次序;
根据宏任务的触发规则和调用次序,确定宏任务的执行次序;

 

下面做個測試:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <script>
        console.log(‘1‘);//
        setTimeout(function () {
            console.log(‘2‘);//
            new Promise(function (resolve) {
                console.log(‘3‘);//
                resolve();
            }).then(function () {
                console.log(‘4‘);//
            })
        }, 0);
        new Promise(function (resolve) {
            console.log(‘5‘);//
            resolve();
        }).then(function () {
            console.log(‘6‘);//
        });
        setTimeout(function () {
            console.log(‘7‘);//
            new Promise(function (resolve) {
                console.log(‘8‘);//
                resolve();
            }).then(function () {
                console.log(‘9‘);//
            });
        })
    </script>
</body>

</html>

测试结果为:   1->5->6->2->3->4->7->8->9

如果上面實在node 环境中

测试结果为:   1->5->6->2->3-->7->8->4->9

 

分析

  setTimeout内部回调函数执行顺序在浏览器环境与node环境是有差异的。
      1.浏览器环境是执行完seTimeout内部回调函数内容 技术图片
第一个setTimeout中的“2 3 4”先与第二个setTimeout中的“7 8 9”打印。
     2.node环境中setTimeout内部如果还有异步操作,直接跳到下一个setTimeout回调代码中。至于两个setTimeout中promose.then内部的执行顺去取决于微任务的入队顺序


以上是关于微任务,宏任务顺序的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript宏任务(macrotask)和 微任务(microtask) 执行顺序

[jS 事件循环理解] 主线程 宏任务 微任务 - 执行顺序优先级理解

关于面试中异步与延时 执行顺序的预期结果问题

微任务和宏任务的区别及具体场景

微任务和宏任务的区别及具体场景

js 宏任务,微任务