JS执行机制

用一些例子做说明:

<script>
    setTimeout(function () {
        console.log("定时器开始啦");
    });
    new Promise(function (resolve) {
        console.log("马上执行for循环");
        for (var i = 0; i < 10000; i++) {
            i == 5 && resolve();
            // console.log(i);
        }
        console.log(i)
    }).then(function () {
        console.log("执行 then 函数啦");
    });
    console.log("代码执行结束");
</script>

 

<script>
    let data = [];
    $.ajax({
        url: 'txt',
        data: data,
        success: () => {
            console.log('发送成功');
        }
    });
    console.log("代码执行结束");

    /*
        上述 Ajax 请求执行顺序:
        ajax 进入 Event Table,注册回调函数 success;
        执行 console.log('代码执行结束')。
        ajax 事件完成,回调函数进入 Event Queue。
        主线程从 Event Queue 读取回调函数 success 并执行。
    */
</script>

 

<script>
    function task() {
        console.log("回调函数");
    }

    function sleep(delay) {
        while (delay) {
            console.log(delay);
            delay--;
        }
    }
    setTimeout(() => {
        task();
    }, 3000);

    sleep(1000000);
    /*
        上述 setTimeout 执行顺序
        1、task() 进入Event Table 并注册,即时开始。
        2、执行 sleep 函数,非常慢,计时仍在继续。
        3、3秒到了,计时事件 timeout 完成,task() 进入Event Queue, 但是 sleep
        也太慢了,还没执行完,只好等着。
        4、sleep 终于执行完了,task() 终于从 Event Queue 进入了主线程执行。
    */
</script>

 

<script>
    setTimeout(function() {
        console.log("setTimeout");
    });
    new Promise(function (resolve) {
        console.log("promise");
        resolve();
    }).then(function () {
        console.log("then");
    });
    console.log("console");
    /*
        promise console then setTimeout
        1、这段代码作为宏任务,进入主线程;
        2、先遇到 setTimeout,那么将其回调函数注册后发到宏任务 Event Queue;
        3、接下来遇到 Promise,new Promise 立即执行【打印 promise】,then 函数分发到微任务 Event Queue;
        4、遇到 console.log(),立即执行【打印 console】;
        5、到这里整体代码 scrip 作为第一个宏任务执行结束,看看有哪些微任务?发现 then 在微任务 Event Queue 里面,执行【打印 then】;
        6、第一轮事件循环结束了,开始第二轮循环,当然从宏任务 Event Queue 开始。发现 Event Queue 中 setTimeout 对应回调函数,立即执行【打印 setTimeout】;
        7、结束啦嘎
    */
</script>

 

<script>
    console.log("1");

    setTimeout(function () {
        console.log("2");
        process.nextTick(function () {
            console.log("3");
        });

        new Promise(function (resolve) {
            console.log("4");
            resolve();
        }).then(function () {
            console.log("5");
        });
    });

    process.nextTick(function () {
        console.log("6");
    });

    new Promise(function (resolve) {
        console.log("7");
        resolve();
    }).then(function () {
        console.log("8");
    });

    setTimeout(function () {
        console.log("9");
        process.nextTick(function () {
            console.log("10");
        });

        new Promise(function (resolve) {
            console.log("11");
            resolve();
        }).then(function () {
            console.log("12");
        });
    });
    /*
        第一轮循环流程
        1、整体 script 作为第一个宏任务进入主线程,遇到 console.log, 【打印 1】;
        2、遇到 setTimeout,其回调函数被分到宏任务 Event Queue 中,记为 setTimeout1;
        3、遇到 process.nextTick(),其回调函数被分发到微任务 Event Queue中,记为 process1;
        4、遇到 Promise, new Promise 直接执行,【打印 7】。then 被分发到微任务 Event Queue 中,记为 then1;
        5、又遇到 setTimeout,其回调函数被分发到宏任务 Event Queue 中,记为 setTimeout2。

        宏任务 Event Queue    微任务 Event Queue
        setTimeout1          process1
        setTimeout2          then1

        上表是第一轮事件循环宏任务结束时各 Event Queue 的情况,此时已经输入 1、7;
        6、发现 process1 和 then1 两个微任务,执行 process1 【打印 6】,执行 then1 【打印 8】;
        7、好了,第一轮事件循环正式结束,这一轮的结果输出 1、7、6、8;
        8、那么第二轮时间循环从 setTimeout1 宏任务开始,首先【打印 2】。接下来遇到 process.nextTick(),同样将其分发到微任务 Event Queue 中,记为 process2,
           new Promise 立即执行,【打印 4】,then 也分发到微任务 Event Queue 中,记为 then2;

        宏任务 Event Queue    微任务 Event Queue
        setTimeout2          process2
                             then2

        9、第二轮事件循环宏任务结束,发现微任务,执行 process2 【打印 3】,执行 then2 【打印 5】;
        10、第二轮事件循环结束,第二轮输出 2、4、3、5;
        11、第三轮事件循环开始,此时只剩 setTimeout2,执行,【打印 9】;
        12、将 process.nextTick() 分发到微任务 Event Queue 中,记为 process3,
            new Promise 立即执行,【打印 11】,then 也分发到 Event Queue 中,记为then3;

        宏任务 Event Queue    微任务 Event Queue
                             process3
                             then3

        13、第三轮事件循环宏任务执行结束,发现微任务,执行 process3 【打印 10】,执行 then3 【打印12】;
        14、第三轮事件循环结束,第三轮输出 9、11、10、12

        整段代码,共进行了三次事件循环,完整输出为 1、7、6、8、2、4、3、5、9、11、10、12
    */
</script>

 

感谢这位老哥:https://juejin.cn/post/6844903512845860872

https://mp.weixin.qq.com/s/7MrFNyN2aNWErTfg12_c_g

posted @ 2021-10-07 15:16  し7709  阅读(22)  评论(0编辑  收藏  举报