JS事件论询解析

一 事件轮询的含义和原理

        JavaScript 事件轮询(event loop)是 JavaScript 运行时环境中的一个机制,它允许 JavaScript 能够执行非阻塞的异步操作。这是因为 JavaScript 在大多数环境下(比如 Web 浏览器、Node.js)中是单线程运行的,意味着在任何给定的时刻它只能执行一个任务。事件轮询使得 JavaScript 能够表现出异步行为,即使它在内部是单线程的。

事件轮询的工作原理大致如下:

1.调用栈(Call Stack): 当代码开始执行时,它首先在调用栈中处理。如果一个函数被执行,它就被添加到调用栈中,当函数执行完成后,它就会被移除。

2.事件队列(Event Queue): 当 JavaScript 运行时环境得到一些不在当前执行堆栈中的事件(例如,用户输入、定时器计时器完成、异步操作完成等)时,这些事件就会被放置到事件队列中。

3.事件循环(Event Loop): 当调用栈清空,即没有更多代码执行时,事件循环就会检查事件队列。如果队列中存在事件,那么事件循环就会依次取出一个事件,并将相关的回调函数放到调用栈中,这样回调函数就可以执行了。

4.Web APIs/Web Platform APIs: 浏览器提供的一些异步API(如 setTimeoutXMLHttpRequest)并不直接由 JavaScript 引擎管理,它们可以被看作是环境级的 Web APIs。当这些 API 操作完成时(如定时器到期),它们会将回调函数放到事件队列中,等待事件循环后续的处理。

二 简单事件轮询解析

       

 console.log('A'); // 第一个
        setTimeout(() => {
          console.log('B'); // 第七个
        }, 0);
        new Promise(resolve=>{
          console.log('C'); // 第二个
          resolve()
        }).then(()=>{
          console.log('D'); // 第五个
        })
      
        setTimeout(() => {
          console.log('E'); // 第八个
          new Promise(resolve=>{
            console.log('F'); // 第九个
            setTimeout(() => {
              console.log('G'); // 第十二个
            });
            resolve()
          }).then(()=>{
            console.log('H'); // 第十个
          })
        }, 0);
        new Promise(resolve=>{
          console.log('I'); // 第三个
          resolve()
        }).then(()=>{
          console.log('J'); // 第六个
          setTimeout(() => {
            console.log('K'); // 第十一个
          });
        })
        console.log('L'); // 第四个

首先事件轮询中 分为 同步任务 异步任务 ,异步任务又分为异步微任务和异步宏任务,同步任务首先进行执行,同步任务执行完,异步微任务进行执行,最后是异步宏任务进行执行,所以只要分清楚什么是同步、什么是异步,这些题就很好做了。

 console.log() 

  new Promise(()=>{

})

是同步任务

Promise 的回调任异步微任务

延时器(setTimeout) 和 定时器(setInterval)是异步宏任务

所以 A C I L是同步任务 安顺序进行执行 后面是 D J 是异步微任务 随后执行 最后是异步宏任务延时器(setTimeout) 中包含的同步任务和异步任务 继续安顺序执行  B E F H K G

同优先级任务 遵循先进先出原则 

三 async和await是 ECMAScript 2017 引入的特性,用于处理异步操作的语法糖。它们可以让异步代码以同步的方式编写,使代码更加清晰和易于理解。

         async function async1(){
          console.log('A'); //2
          await async2()
          console.log('B');//6
        }
        async function async2(){
          console.log('C'); //3
        }
        console.log('D'); //1
        setTimeout(function() {
          console.log('E');//8
        }, 0);
        async1()
        new Promise(function(resolve){
          console.log('F');//4
          resolve()
        }).then(function(){
          console.log('G'); //7
        })
        console.log('H');//5

输出结果为 D A C F H B G E

其中await 可以简单理解为Promise的封装 

     async function foo() {
        console.log(1);
        await bar();
        console.log(2);
      }
      async function bar() {
        console.log(3);
      }
      foo();
      console.log(4); //1342

上面这段代码可以简单解析为

         function foo(){
        console.log(1);
        new Promise(resolve=>{
            bar()
            resolve()
        }).then(()=>{
            console.log(2);
        })
      }
      function bar(){
        console.log(3);
      }
      foo()
      console.log(4);

 四 那些任务是异步微任务 那些任务是异步宏任务

异步微任务

  • Promise 的 thencatch 和 finally 方法会创建微任务。
  • MutationObserver 的回调函数也会创建微任务。
  • 通过 queueMicrotask 函数添加的任务也是微任务。

异步宏任务

  • setTimeout 和 setInterval 函数会创建宏任务。
  • 用户交互事件(如点击、键盘事件等)也是宏任务。
  • requestAnimationFrame 方法也创建一个宏任务。

 JavaScript引擎内部的方法都是异步微任务 

浏览器方法是异步宏任务

以上只是简单解析 需要更深入可以参考飞翔@向方 这位大佬的文章js中异步要发生的一些事_异步会发生什么-CSDN博客

你可能感兴趣的:(javascript,开发语言,前端)