事件循环Event Loop介绍(微任务、宏任务介绍)

615 阅读2分钟

事件循环

事件循环其实就是浏览器解析js代码的一种运行机制或者一种执行规则。
我认为的事件循环就是事件队列,就好像js代码可以分为同步代码以及异步代码(微任务、宏任务),而浏览器执行这些js代码的先后顺序就叫做事件循环。

异步任务主要有

事件、网络请求(ajax)、定时器、promise.then()、async/await

宏任务:

事件、网络请求(ajax)、定时器

微任务:

promise.then()、async/await

事件循环执行机制

1 首先进入到script标签中,就先当于进入了第一次的事件循环
2 遇到同步代码,立即执行
3 遇到宏/微任务,把它们放入到宏/微任务队列中
4 执行完毕所有的同步代码
5 执行微任务代码
6 完成所有的微任务代码,执行宏任务代码,直至所有的宏任务队列清空
注意: 1 宏/微任务的内部执行顺序与上面的六步完全一样 2 如果多个script标签,它的执行权重应该是在微任务的后面,宏任务的前面 以下用代码进行解释:

第一题:

 <script>
 
        console.log(1)
        
        setTimeout(function () {
            console.log(2)
        }, 0)
        
        const p = new Promise((resolve, reject) => {
            resolve(1000)
        })
        
        p.then(data => {
            console.log(data)
        })

        console.log(3)

    </script>

执行结果:1 3 1000 2
解析:1和3为同步,直接输出;2为宏任务;1000为微任务

第二题:

<script>
        console.log(1)
        setTimeout(function () {
            console.log(2)
            new Promise(function (resolve) {
                console.log(3)
                resolve()
            }).then(function () {
                console.log(4)
            })
        })

        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)
            })
        })
        console.log(10)
    </script>

执行结果:1 5 10 6 2 3 4 7 8 9
解析:
第一步:1 5 10为同步,直接输出;还有三个函数分别为定时器、promise、定时器
第二步:执行promise,输出6(promise中只有.then才是异步,promise仅仅是容器,里面的代码执行与否取决于代码本身)
第三步:执行第一个定时器;里面2 3为同步,4为异步,按序输出
第四步:第二个定时器与上面一致

第三题:

<script>
        new Promise((resolve, reject) => {
            resolve(1)

            new Promise((resolve, reject) => {
                resolve(2)
            }).then(data => {
                console.log(data)
            })

        }).then(data => {
            console.log(data)
        })

        console.log(3)
    </script>

执行结果:3 2 1
解析: 3是同步;promise内部代码执行完毕才会调用then,所以先输出2 然后是1

第四题:

<script>
        setTimeout(() => {
            console.log(1)
        }, 0)
        new Promise((resolve, reject) => {
            console.log(2)
            resolve('p1')

            new Promise((resolve, reject) => {
                console.log(3)
                setTimeout(() => {
                    resolve('setTimeout2'); //'混淆你的'
                    console.log(4)
                }, 0)
                resolve('p2')
            }).then(data => {
                console.log(data); //'p2'
            })

            setTimeout(() => {
                resolve('setTimeout1'); //'混淆你的'
                console.log(5)
            }, 0)
        }).then(data => {
            console.log(data); //'p1'
        })
        console.log(6)
    </script>

执行结果:2 3 6 p2 p1 1 4 5
解析:2 3 6是同步,定时器函数最后执行,所以先执行p2 p1,然后定时器按先后顺序执行

第五题:

<script>
        console.log(1);
        async function fnOne() {
            console.log(2);
            await fnTwo(); // 右结合先执行右侧的代码, 然后等待
            console.log(3);
        }
        async function fnTwo() {
            console.log(4);
        }
        fnOne();

        setTimeout(() => {
            console.log(5);
        }, 2000);

        let p = new Promise((resolve, reject) => { // new Promise()里的函数体会马上执行所有代码
            console.log(6);
            resolve();
            console.log(7);
        })

        setTimeout(() => {
            console.log(8)
        }, 0)

        p.then(() => {
            console.log(9);
        })
        console.log(10);
    </script>
    <script>
        console.log(11);
        setTimeout(() => {
            console.log(12);
            let p = new Promise((resolve) => {
                resolve(13);
            })
            p.then(res => {
                console.log(res);
            })
            console.log(15);
        }, 0)
        console.log(14);
    </script>

执行结果:1 2 4 6 7 10 3 9 11 14 8 12 15 13 5
解析:有两个script标签;先看第一个,1 2 4 6 7 10为同步,async里面只有await是异步的,不过阻隔的不是await后面的函数,而是await下面的代码,然后输出3,再执行promise,上面的script剩下两个定时器了,最后执行,执行下面的script,输出11 14,再依次执行定时器。