likes
comments
collection
share

浏览器事件循环机制,你真的理解吗

作者站长头像
站长
· 阅读数 16

JS引擎在运行我们编写的代码时,是按语句依次执行的。前面的JS代码没有执行完毕,后面的将会堵塞。

同步任务、异步任务

在JS中,任务分为同步任务和异步任务。像声明定义变量,判断语句,循环语句,打印语句都是同步任务。而异步任务有:setTimeout,setInterval,Promise,MutationObserver等。

宏任务、微任务

异步任务又可分为宏任务与微任务。

宏任务:setTimeout, setInterval, setImmediate(IE特有)

微任务:Promise, MutationObserver ,process.nextTick(node特有)*

JS引擎在运行我们的代码时,遇到宏任务或微任务时,会将其放入对应的宏任务队列或微任务队列中。当同步任务执行完后,再执行异步任务。任务队列里的任务采取先进先出的原则,即先进队列的任务先执行。

完整执行顺序

1,从上往下执行

2,如果是同步任务,就立即执行

3,如果是宏任务,放到宏任务队列中

4,如果是微任务,放到微任务队列中

5,当同步任务全部执行完毕后,按先进先执行的方式执行所有满足条件的微任务。

6,当微任务队列中满足条件的任务全部执行完毕后,就去执行一条宏任务队列中满足条件的宏任务

7,然后再去执行微任务队列中所有满足条件的微任务

8,反复循环

注意:当满足条件的微任务执行完后,不是去执行所有满足条件的宏任务。而是再执行完一条宏任务后,如果当前没有同步任务,就会去立即执行所有满足条件的微任务。

代码解析

// 定义一个宏任务 s1
setTimeout(function () {
    console.log("s1");
    // 定义一个微任务 p1
    Promise.resolve().then(function () {
        console.log("p1");
    });
    // 定义一个微任务 p2
    Promise.resolve().then(function () {
        console.log("p2");
    });
}, 0);
// 定义一个微任务 p3
Promise.resolve().then(function () {
    console.log("p3");
    // 定义一个宏任务 s2
    setTimeout(function () {
        console.log("s2");
    });
    // 定义一个宏任务 s3
    setTimeout(function () {
        console.log("s3");
    });
});

1,没有同步任务

2,先执行微任务p3,输出p3

3,依次添加宏任务s2,s3到宏任务队列中,

4,微任务p3执行完毕

5,微任务队列没有其他可执行微任务

6,执行宏任务s1,输出s1

7,依次添加微任务p1,p2到微任务队列中

8,宏任务s1执行完毕,

9,执行微任务队列中可执行的任务,输出p1,p2

10,取一条宏任务s2执行,输出s2

11,微任务队列为空,且没有同步任务

12,执行下一条宏任务s3,输出s3

结果:p3,s1,p1,p2,s2,s3

浏览器事件循环机制,你真的理解吗