美文网首页
js事件机制(答应我耐心看)

js事件机制(答应我耐心看)

作者: 壮壮仔儿 | 来源:发表于2022-06-26 18:39 被阅读0次

    event loop 决定js代码的执行顺序为了协调事件,用户交互,脚本,渲染,网络等

    \color{#0580CF} {一个event loop有一个或者多个task队列。}
    当用户代理安排一个任务,必须将该任务增加到相应的event loop的一个tsak队列中。

    每一个task都来源于指定的任务源,比如可以为鼠标、键盘事件提供一个task队列,其他事件又是一个单独的队列。可以为鼠标、键盘事件分配更多的时间,保证交互的流畅。

    task也被称为macrotask,是一个先进先出的队列,由指定的任务源去提供任务。

    task/macrotask任务源:

    • setTimeout
    • setInterval
    • setImmediate
    • I/O
    • UI rendering

    \color{#0580CF} {每一个event loop都有一个microtask队列,一个microtask会被排进microtask队列而不是task队列。}
    microtask 队列和task 队列有些相似,都是先进先出的队列,由指定的任务源去提供任务,不同的是一个
    event loop里只有一个microtask 队列。
    microtask任务源:

    • process.nextTick
    • promises
    • Object.observe
    • MutationObserver

    event loop的循环过程:

    1. 在tasks队列中选择最老的一个task,用户代理可以选择任何task队列,如果没有可选的任务,则跳到下边的microtasks步骤。
    2. 将上边选择的task设置为正在运行的task。
    3. Run: 运行被选择的task。
    4. 将event loop的currently running task变为null。
    5. 从task队列里移除前边运行的task。
    6. Microtasks: 执行microtasks任务检查点。(也就是执行microtasks队列里的任务)
    7. 更新渲染(Update the rendering)...
    8. 如果这是一个worker event loop,但是没有任务在task队列中,并且WorkerGlobalScope对象的closing标识为true,则销毁event loop,中止这些步骤,然后进行定义在Web workers章节的run a worker。
    9. 返回到第一步。

    概括:
    \color{#0580CF} {event loop会不断循环的去取tasks队列的中最老的一个任务推入栈中执行,}
    \color{#0580CF} {并在当次循环里依次执行并清空microtask队列里的任务。}

    \color{#0580CF} {执行完microtask队列里的任务,有可能会渲染更新。}
    \color{#0580CF} {浏览器很聪明,在一帧以内的多次dom变动浏览器不会立即响应,而是会积攒变动以最高60HZ的频率更新视图}

    microtasks检查点(microtask checkpoint)

    1. 将microtask checkpoint的flag设为true。
    2. Microtask queue handling: 如果event loop的microtask队列为空,直接跳到第八步(Done)。
    3. 在microtask队列中选择最老的一个任务。
    4. 将上一步选择的任务设为event loop的currently running task。
    5. 运行选择的任务。
    6. 将event loop的currently running task变为null。
    7. 将前面运行的microtask从microtask队列中删除,然后返回到第二步(Microtask queue handling)。
    8. Done: 每一个environment settings object它们的 responsible event loop就是当前的event loop,会给environment settings object发一个 rejected promises 的通知。
    9. 清理IndexedDB的事务。
    10. 将microtask checkpoint的flag设为flase。

    task和microtask都是推入栈中执行的,

    主线程类似一个加工厂,它只有一条流水线,待执行的任务就是流水线上的原料,只有前一个加工完,后一个才能进行。event loops就是把原料放上流水线的工人。只要已经放在流水线上的,它们会被依次处理,称为同步任务。一些待处理的原料,工人会按照它们的种类排序,在适当的时机放上流水线,这些称为异步任务。

    setTimeout(function() {
        console.log('setTimeout');
    })
    
    new Promise(function(resolve) {
        console.log('promise');
    }).then(function() {
        console.log('then');
    })
    
    console.log('console');
    
    

    task:script microtask:

    取出script推入栈中执行,promise立即执行以及打印

    settimeout为task,then为microtask

    【task队列:settimeout;microtask队列:then】

    执行microtask,进行下一项

    从task队列取出settimeout,推入栈中执行

    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')
        })
    })
    

    task:script microtask:

    取出script推入栈中执行,打印1,setTimeout为task,nextTick为microtask,打印7,then为microtask,setTimeout为task

    【task队列:settimeout1 setTimeout2 ;microtask队列:nextTick then】

    执行microtask打印6以及8,进行下一项

    【task队列:setTimeout1 setTimeout2;microtask队列:】

    从task队列取出settimeout1,推入栈中执行,打印2,setTimeout-nextTick为microtask,立即执行Promise打印4,setTimeout-then为microtask

    【task队列:setTimeout2;microtask队列: setTimeout-nextTick setTimeout-then】

    执行microtask打印3以及5,进行下一项

    【task队列:setTimeout2;microtask队列:】

    从task队列取出settimeout2,推入栈中执行,打印9,setTimeout2-nextTick为microtask,立即执行Promise打印11,setTimeout2-then为microtask

    【task队列:;microtask队列:setTimeout2-nextTick setTimeout2-then】

    打印打印10,打印12

    相关文章

      网友评论

          本文标题:js事件机制(答应我耐心看)

          本文链接:https://www.haomeiwen.com/subject/wdegvrtx.html