JavaScript事件循环

作者: Joemoninni | 来源:发表于2020-12-24 10:42 被阅读0次

    Tasks(任务),microtasks(微任务),queues(队列),schedules(调度):

    举个例子:

    console.log('script start'); // 1.task1
    
    setTimeout(function () {
      console.log('setTimeout'); // 2.task2
    }, 0);
    
    Promise.resolve()           
      .then(function () {        // 3.加入microtasks aqueue
        console.log('promise1'); 
      })
      .then(function () {
        console.log('promise2');
      });
    
    console.log('script end'); // 4.task1的script运行结束,执行微任务microtasks,这时task1执行结束,结束后再执行task2
    
    // output:
    /** 
    *   script start
    *   script end
    *   promise1
    *   promise2
    *   setTimeout
    */
    

    为什么会这样?往下看...👇

    Getting from a mouse click to an event callback requires scheduling a task, as does parsing HTML, setTimeout.

    从鼠标点击到事件回调需要调度一个任务,解析HTML也是如此,setTimeout也是如此。

    注:可以把解析HTML,setTimeout看成是任务。

    上面的setTimeout等待指定的延迟时间,然后为它的回调函数调度一个新的任务,这也是为什么setTimeout会在script end后面被打印。因为script end是第一个任务的一部分,而setTimeout是被记录在一个单独的任务中,(也就是第二个任务中,事情总得一件一件来完成,先完成第一个任务,再完成第二个任务)。

    当前运行的script脚本必须在处理microtasks(微任务)之前完成,而microtasks(微任务)总是在下一个task任务之前发生(即微任务总是在每个旧任务的末尾被处理)

    处理微任务的前提是Js Stack(js调用栈)为空。

    如果微任务队列中已经存在一个正在排队的mutation observers,则无法再添加另一个到队列中。

    微任务期间遵循队列排队,即先进先出,先排先执行。

    哪些是微任务?比如观察者回调,promise的回调

    // Let's get hold of those elements
    var outer = document.querySelector('.outer');
    var inner = document.querySelector('.inner');
    
    // Let's listen for attribute changes on the
    // outer element
    new MutationObserver(function () {          
      console.log('mutate');
    }).observe(outer, {
      attributes: true,
    });
    
    // Here's a click listener…
    function onClick() {
      console.log('click');
    
      setTimeout(function () {
        console.log('timeout');
      }, 0);
    
      Promise.resolve().then(function () {
        console.log('promise');
      });
    
      outer.setAttribute('data-random', Math.random());
    }
    
    // …which we'll attach to both elements
    inner.addEventListener('click', onClick);
    outer.addEventListener('click', onClick);
    
    inner.click();
    
    // tasks:
    // microtasks:
    // js stack:
    // log:
    
    

    具体实现参考https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

    相关文章

      网友评论

        本文标题:JavaScript事件循环

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