Axıs
目录

第十六章 EventLoop(Browser)

第十六章 任务队列

定时器

定时器作为宏任务,在执行时,会先将定时器任务进行计时,待主线程运行完毕后,立即执行。
    setTimeout(() => {
        console.log("主任务队列,排列1,运行2");
    }, 2000)
    setTimeout(() => {
        console.log("主任务队列,排列2,运行1");
    }, 1000)
    Promise.resolve().then(() => {
        console.log("微任务队列")
    })
    console.log("主线程任务");

Promise微任务执行逻辑

Promise主体是主线程任务,Promise.then是微任务,
    setTimeout(() => {
        console.log("宏任务");
    }, 1000);
    new Promise(resolve => {
        console.log("立即执行,属于主线程任务");
        resolve();
    }).then(resolve => {
        console.log("then属于微任务");
    })

DOM渲染逻辑

进行DOM渲染时,默认从上到下执行js代码,
如果将script标签放在头部,且js代码执行时间较长,会给用户造成一种页面有问题的感觉。
实际上执行主线程的时候是这样子的。

所以这就是为什么要将script标签放在body之后的原因。

同步

同步指的是队列顺序下的执行。
同步不等于同时。只是间隔时间比较小,最重要的是同步是有顺序的
    let i = 0; //主线程任务
    setTimeout(() => {
        console.log(++i);
    }, 1000)//宏任务队列1 使用主线程i=0,进行操作后,i=1
    setTimeout(() => {
        console.log(++i);
    }, 1000)//宏任务队列2 使用宏任务队列1 i=1,进行操作后i=2

任务轮询

    <div class="demo">1%</div>

    <style>
        .demo {
            display: flex;
            align-items: center;
            justify-content: center;
            border: solid 2px #aaa;
            height: 50px;
            width: 1px;
            background: #a44f;
        }
    </style>

function handle() {
        let i = 0;
        let div = document.querySelector(".demo");
        (function run() {
            if (i < 100) {
                setTimeout(() => {
                    ++i;   //关键在这,即便是执行console.log(++i),i也会在任务队列里进行++i操作
                    div.innerHTML = i + "%";
                    div.style.width = i + "px";
                    run();
                }, 10)
            }
        })()
    }
    handle()

任务拆分

机器的任务拆分和人相似。
当面对大量计算时,使用拆分效果会更好。

function question_exposed() {
        let num = 987654321;
        let res = 0;
        for (let i = 0; i <= num; i++) {
            res += num--
        }
        console.log(res)
    }
    question_exposed();
    console.log("this is main")


任务拆分并没有本质上减少任务量,只是对于人来说,我们能够知道进度。不过这一点十分重要
    let num = 98765;
    let res = 0;
    function question_exposed() {
        for (let i = 0; i <= num; i++) {
            if (num <= 0) break;
            res += num--
        }
        if (num > 0) {
            console.log(num)
            setTimeout(question_exposed)
        } else {
            console.log(res)
        }
    }
    question_exposed();
    console.log("this is main")

Promise微任务处理

有些数据需要在后台进行计算,而前台专注于任务显示。
在后台计算的数据,我们往往需要拿到数据的结果,进行后续的计算。

    async function get_res() {
        let res = await Promise.resolve().then(() => {
            let count = 0;
            for (let i = 0; i <= num; i++) {
                count += num--;
            }
            return count;
        })
        console.log(res);
    }
    let num = 9890000;
    get_res(num);
    console.log("main")