事件循环题

前言:

在这之前,先介绍一下Js是一个单线程的语言,代码是从上到下执行的,遇到同步的代码,当有些代码是异步的时候,并不会停下来,如果停下来的话非常的耗时间,所以这个时候就有任务队列这个概念,当遇到异步的代码的时候,并不会等待异步代码执行完毕才执行下面的代码,而是将异步的代码放入任务队列里面,然后拿到主线程里面去执行。如此的循环下去被称为事件循环

一.小试牛刀


    setTimeout(function () {
  
      console.log(1)
    }, 0);

    new Promise(function executor(resolve) {
      console.log(2);
      for (var i = 0; i < 10000; i++) {
       
        i == 9999 && resolve();
      }
      console.log(3);
    }).then(function () {
   
      console.log(4);
    });
    console.log(5);

分析代码:

主线程: console.log(2); console.log(3);   console.log(5);

异步: console.log(4)------微任务, console.log(1)------宏任务

因为: 微任务的优先级大于宏任务的优先级

最终执行的结果是: 2, 3, 5,4 ,1

图示:

二.测试测试

   // 1、2、3、before timeout、alse before timeout、4、test
    setTimeout(() => {
      // #1
      new Promise(resolve => {
        resolve();
      }).then(() => {
        // #6
        console.log('test');
      });

      console.log(4);
    });

    new Promise(resolve => {
      // 一旦调用了 resolve 就把后面的 then 对应的回调添加到了微任务队列
      resolve();
      console.log(1)
    }).then(() => {
      // #2
      console.log(3);
      // 执行 Promise.resolve() 又把后面的 then 添加到了微任务队列
      Promise.resolve().then(() => {
        // #3
        console.log('before timeout');
        // 函数默认返回 undefined
        // then 的函数其实返回默认的 Promise.resolve(undefined)
        // return Promise.resolve(undefined) // 隐藏!!!
      }).then(() => {
        // #4
        Promise.resolve().then(() => {
          // #5
          console.log('also before timeout')
        })
      })
    })
    console.log(2);

主线程: console.log(1), console.log(2);

任务队列:先执行微任务 : console.log(3); before timeout;also before timeout;

               在执行定时器宏任务: console.log(4);   定时器的微任务:console.log('test');

最终执行的结果是:

 1,2,3,before timeout,also before timeout,4,test。

三.变态测试

setTimeout(() => {
      // #1
      new Promise(resolve => {
        resolve();
      }).then(() => {
        // #4
        console.log('test');
      });

      console.log(4);
      setTimeout(function () {
        // #5
        Promise.resolve().then(res => {
          // #10
          console.log(444);
        })
      })
      Promise.resolve().then(res => {
        // #6
        console.log(888);
      })
    });

    new Promise(resolve => {
      resolve();
      console.log(1)
    }).then(() => {
      // #2
      console.log(3);
      setTimeout(function () {
        // #3
        Promise.resolve().then(() => {
          // #7:这一行确确实实打印了 before timeout,但是执行完毕后又产生了一个微任务
          console.log('before timeout');
          // return Promise.resolve(undefined)
        }).then(() => {
          // #8
          Promise.resolve().then(() => {
            // #9
            console.log('also before timeout')
          })
        })
      })
    })
    console.log(2);

代码分析:

主线程:console.log(1), console.log(2);

任务队列:console.log(3)------------微任务;剩下两个定时器是宏任务。

执行第一个定时器,console.log(4); 定时器的第一个微-test---定时器中的第二个微。同时又生成一个定时器,执行第二个定时器,before timeout,它的回调又产生了一个微任务打印also before timeout。执行最有一个定时器,打印444。

最终的执行结果是:1, 2,3,4,test,before timeout,also before timeout,444。

图示:

 四.再测一测

 Promise.resolve().then(() => {
      // #1
      Promise.resolve().then(r => {
        // #2
        console.log('a');
        // return Promise.resolve(undefined)
      }).then(r => {
        // #4
        console.log('h');
      }).then(r => {
        // #6
        console.log('8');
      }).then(r => {
        // #8
        console.log('99')
      });
      // return Promise.resolve(undefined)
    }).then(r => {
      // #3
      console.log('44');
    }).then(() => {
      // #5
      console.log('66')
    }).then(() => {
      // #7
      console.log('7')
    })

代码分析:

主线程:

执行这个异步的时候,同时产生了两个异步。  return Promise.resolve(undefined)

任务队列:

 console.log('a');

 console.log('44');

主线程开始执行:

console.log('a');  console.log('44');

执行完a-----------产生新的微任务 console.log('h');

执行完44-------- 产生新的微任务  console.log('66')

主线程开始执行:console.log('h');  console.log('66')

如此交替下去.最终的执行结果是:

 console.log('a');console.log('44');console.log('h');  console.log('66'); console.log('8');console.log('7'); console.log('99')。
图示:

 五.继续测试

                       

代码分析: 

此时的任务队列: 产生微任务111---------222。

 主线程:

111, 

此时的微任务队列:

222

333

主线程继续执行:

222 

微任务队列

333  444-666   555

主线程继续执行:

333 444 555  666

综上所述:

111,222,333,444,555,666

六.冲击最后一道题

function func(num) {
      return function () {
        // #1
        console.log(num)
      };
    }
    setTimeout(func(1));
    async function async3() {
      // # 这里调用 async4 确实直接打印了 5,但同时产生一个微任务
      await async4();
      // #2
      console.log(8);
    }
    async function async4() {
      console.log(5)
    }
    // !只要调马上就会执行
    async3();

    function func2() {
      // #3
      console.log(2);
      async function async1() {
        await async2();
        // #6
        console.log(9)
      }
      async function async2() {
        console.log(5)
      }
      async1();
      setTimeout(func(4))
    }
    setTimeout(func2);
    setTimeout(func(3));
    new Promise(resolve => {
        console.log('Promise');
        resolve()
      })
      .then(() => console.log(6)) // #4
      .then(() => console.log(7)); // #5
    console.log(0);

解析代码:

做这道题之前首先要知道await后面的代码是异步的。

第一遍走完:

主线程:

   console.log(5)

  console.log('Promise');

  console.log(0);

宏任务:

 setTimeout(func(1));

setTimeout(func2);

  setTimeout(func(3));

微任务:

  console.log(8);

 console.log(6)

回调:

 console.log(6)-----------console.log(7))

主线程要拿微任务去执行

主线程:

  console.log(8);

 console.log(6)

console.log(7))-----------回调也产生异步任务

目前输出的结果:

   console.log(5)

  console.log('Promise');

  console.log(0);

  console.log(8);

 console.log(6)

console.log(7))-----------回调也产生异步任务

开始处理宏任务:

 setTimeout(func(1));------------------1

setTimeout(func2);

 console.log(2); 

 console.log(5)

产生微任务:   console.log(9)

产生宏任务: setTimeout(func(4))

目前的宏任务: setTimeout(func(3));  setTimeout(func(4))

在去执行:

输出:1 ,2,5,9,3,4

最终执行的结果是:

 console.log(5)

  console.log('Promise');

  console.log(0);

  console.log(8);

 console.log(6)

console.log(7))-----------回调也产生异步任务

1 ,2,5,9,3,4

图示:

好的,我会尽力回答您的问前端事件循环机制是指在浏览器中,所有的 JavaScript 代码都是通过事件循环来执行的。事件循环是一种机制,用于协调 JavaScript 代码的执行顺序,以确保所有的代码都能够按照正确的顺序执行。下面是一个简单的前端事件循环机制的面试: 1. 请简述前端事件循环机制的执行流程。 答:前端事件循环机制的执行流程主要包括以下几个步骤: 1)收集任务:将所有需要执行的任务加入到任务队列中。 2)执行任务:根据任务队列中的任务类型,将其分为宏任务和微任务。 3)执行宏任务:从宏任务队列中获取一个宏任务进行执行。 4)执行微任务:在宏任务执行期间,如果产生了微任务,将其加入到微任务队列中。 5)清空微任务:在宏任务执行结束后,清空微任务队列中的所有任务。 6)重复执行:重复执行步骤 3~5,直到任务队列中没有任务可以执行。 2. 请简述宏任务和微任务的区别。 答:宏任务和微任务是前端事件循环机制中的两种任务类型。宏任务是指一些较为耗时的任务,比如 setTimeout、setInterval、ajax 请求等。而微任务是指一些较为简单、执行时间较短的任务,比如 Promise.then、MutationObserver 等。 宏任务和微任务的执行顺序有所不同,具体来说,宏任务会在本轮事件循环的末尾执行,而微任务会在本轮事件循环的末尾执行完所有的宏任务后立即执行。这也就是为什么在 Promise.then 中产生的微任务会先于 setTimeout 中的宏任务执行的原因。 希望我的回答能够对您有所帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值