zoukankan      html  css  js  c++  java
  • 简述Js的事件循环

    普通消息队列

    一个代码块中的所有同步代码,都会被看作一个宏任务,添加到普通消息队列的尾部

    延迟执行队列

    当你在代码中使用 setTimeout 或 setInterval 时,会创建一个宏任务
    延迟指定的时间后,将其放入延迟执行队列的尾部

    事件循环系统

    为了简化叙述,我们可以理解为:每一轮事件循环都执行一个宏任务,每一轮事件循环都关联一个微任务队列
    具体过程如下:

    • 检查普通消息队列是否为空,若不为空,则从队列头部取出一个宏任务执行;否则,从延迟执行队列头部取出一个宏任务执行
    • 执行过程中如果遇到 setTimeout 或 setInterval,延迟指定时间后,将其作为一个宏任务 添加到延迟执行队列的尾部
    • 执行过程中如果创建了微任务(Promise 或者 MutationObserver),就将它添加到当前的微任务队列中
    • 执行当前微任务队列中的所有微任务
    • 开始下一个循环

    例题1:

    console.log('--开始--');
    
    setTimeout(() => {
      console.log('timer1');  
    }, 0);
    
    new Promise((resolve, reject) => {
      for (let i = 0; i < 5; i++) {
        console.log(i);
      }
      resolve()
    }).then(()=>{
      console.log('Promise'); 
    })
    
    console.log('--结束--');
    
    //---开始--
    //0
    //1
    //2
    //3
    //4
    //--结束--
    //Promise
    //timer1
    

    第一轮循环:普通消息队列中只有一个宏任务(整个script)

    • 遇到console.log,直接输出 "--开始--"
    • 遇到setTimeout,因为指定时间为0ms,所以立即将其回调函数timer1添加到延迟执行队列的尾部
    • 遇到Promise的executor,直接执行,依次输出0、1、2、3、4,遇到resolve,将其回调函数添加到当前的微任务队列中
    • 遇到console.log,直接输出 “--结束--”
    • 检查微任务队列,发现一个微任务,立即执行,输出“Promise”

    第二轮循环:普通消息队列为空,延迟执行队列中有一个宏任务(timer1)

    • 执行timer1的回调函数
    • 发现微任务队列为空,本轮循环结束

    例题2:

    new Promise((resolve) => {
      console.log('this is executor');
      resolve();
    }).then(() => {
      console.log('this is resolve');
      setTimeout(() => { // 命名为timer1
        console.log('timer1');
      }, 4)
    })
    
    setTimeout(() => { // 命名为timer2
      console.log('timer2');
    }, 4)
    
    console.log('-- 结束--');
    
    //this is executor
    //-- 结束--
    //this is resolve
    //timer2
    //timer1
    

    第一轮循环:普通消息队列中只有一个宏任务(整个script)

    • 遇到Promise的executor,直接执行,输出“this is executor”
    • 遇到resolve,将其回调函数添加到当前的微任务队列中
    • 遇到setTimeout,在4ms后将timer2添加到延迟执行队列的尾部
    • 遇到console.log,直接输出 “--结束--”
    • 检查微任务队列,发现一个微任务,立即执行
    • 遇到console.log,直接输出 “this is resolve”
    • 遇到setTimeout,在4ms后将timer1添加到延迟执行队列的尾部,本轮循环结束

    第二轮循环:普通消息队列为空,延迟执行队列头部为timer2

    • 执行timer2,输出timer2

    第三轮循环:延迟执行队列头部为timer1

    • 执行timer1,输出timer1
  • 相关阅读:
    P1064 金明的预算方案
    P1164 小A点菜
    P1346 电车
    01背包二进制优化
    2018暑期多校1
    牛课第二次多校I
    STL
    Reachability from the Capital
    P2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
    P3387 【模板】缩点
  • 原文地址:https://www.cnblogs.com/baebae996/p/14096938.html
Copyright © 2011-2022 走看看