JS单线程、宏任务与微任务的执行顺序


前言


一、js 单线程

众所周知js是单线程,但js是可以执行同步和异步任务的,同步的任务众人皆知是按照顺序去执行的;

而异步任务的执行,是有一个优先级的顺序的,包括了 **宏任务 Macro task(Macrotasking)**和 微任务(microtasks)

二、宏任务

是指消息队列中的等待被主线程执行的事件,宏任务执行时都会重新创建栈,然后调用宏任务中的函数,栈也会随着变化,但宏任务执行结束时,栈也会随之销毁。

包括 整体代码script,setTimeout,setInterval ,setImmediate,I/O,UI renderingnew ,Promise

三、微任务

可以把微任务看成是一个需要异步执行的函数,*执行时机是在主函数执行结束之后、当前宏任务结束之前*

包括 Promises.(then catch finally),process.nextTick,MutationObserver

微任务是基于消息队列、事件循环、UI 主线程还有堆栈而来的

四、区别

宏任务和微任务的区别在于在事件循环机制中,执行的机制不同

每次执行完所有的同步任务后,会在任务队列中取出异步任务,先将所有微任务执行完成后,才会执行宏任务
所以可以得出结论, 微任务会在宏任务之前执行。
我们在工作常用到的宏任务是 setTimeout,而微任务是 Promise.then

注意这里是Promise.then,也就是说 new Promise在实例化的过程中所执行的代码是同步的,而在 then中注册的回调函数才是异步。

五、代码示例

示例一:

在这里插入图片描述

示例代码:

<!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>代码执行顺序</title>
</head>

<body>

</body>
<script>
    setTimeout(function () {
        console.log("set1")
        new Promise(function (resolve) {
            resolve()
        }).then(function () {
            console.log("then3")
        })
        setTimeout(function () {
            console.log("宏任务")
          })
    })
    new Promise(function (resolve) {
        console.log("pr1")
        resolve()
    }).then(function () {
        console.log("then")
    })
    setTimeout(function () {
        console.log("set2")
    })
    new Promise(function (resolve) {
        resolve()
    }).then(function () {
        console.log("then2")
    })
    console.log(3)
</script>

</html>

示例二:

在这里插入图片描述

<!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>126435</title>
</head>

<body>

</body>
<script>
    // 1 2 6 4 3 5

    async function async1() {
        console.log(1)
        const result = await async2()
        console.log(3)
    }
    async function async2() {
        console.log(2)
    }
    Promise.resolve().then(() => {
        console.log(4)
    })
    setTimeout(() => {
        console.log(5)
    })
    async1()
    console.log(6)

</script>

</html>

示例三:

在这里插入图片描述

<!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>

</body>
<script>
    console.log('script start')
    async function async1() {  //语法糖 async2()执行完毕 才执行下面 会加入在微观任务里面
        await async2()
        console.log('async1 end')
    }
    async function async2() {
        console.log('async2 end')
    }
    async1()
    setTimeout(function () {
        console.log("setTimeout100")
    }, 100)
    setTimeout(function () {
        console.log("setTimeout")
    }, 0)
    new Promise(resolve => {
            console.log('promise')
            resolve()
        }).then(function () {
            console.log("promise1")
        })
        .then(function () {
            console.log("promise2")
        })
    console.log('script end')
</script>

</html>

示例四:

在这里插入图片描述

<!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>

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

    function bar() {
        console.log('8')
        foo()
    }

    function foo() {
        console.log('9')
    }
    console.log('10')
    bar()
</script>
</html>

总结

解析示例四:
首先浏览器执行Js代码由上至下顺序,遇到setTimeout,把setTimeout分发到宏任务Event Queue中
new Promise属于主线程任务直接执行打印2
Promis下的then方法属于微任务,把then分到微任务 Event Queue中
console.log(‘4’)属于主线程任务,直接执行打印4
又遇到new Promise也是直接执行打印5,Promise 下到then分发到微任务Event Queue中
又遇到setTimouse也是直接分发到宏任务Event Queue中,等待执行
console.log(‘10’)属于主线程任务直接执行
遇到bar()函数调用,执行构造函数内到代码,打印8,在bar函数中调用foo函数,执行foo函数到中代码,打印9
主线程中任务执行完后,就要执行分发到微任务Event Queue中代码,实行先进先出,所以依次打印3,6
微任务Event Queue中代码执行完,就执行宏任务Event Queue中代码,也是先进先出,依次打印1,7。
最终结果:2,4,5,10,8,9,3,6,1,7

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值