浏览器事件循环

本文解析了JavaScript单线程中的异步执行是如何通过宏任务(如setTimeout、setInterval)和微任务(如Promise.then)来实现的,以及它们在事件循环和DOM渲染中的作用。通过实例说明了宏任务与微任务的执行优先级和浏览器事件循环的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

js是一个单线程的脚本语言。  意味着每次只能去做一件事情,不会存在同时执行另一行代码。

那我们的异步方法又是如何实现的呢?

宏任务和微任务

宏任务(macro task)

  • script(整体代码)
  • setTimeout
  • setInterval
  • I/O
  • UI交互事件
  • postMessage
  • MessageChannel
  • setImmediate(Node.js 环境)

简单理解就是web api

微任务(micro task)

  • Promise.then
  • Object.observe
  • MutaionObserver
  • process.nextTick(Node.js 环境)

就是promise (async/await就是promise的语法糖)

例子

function test(){
   console.log('a');
   setTimeout(()=>{
     console.log('c')
   })
   console.log('b');
}

一个简单的例子,输出结果是//a b c

首先js在运行代码的时候,会从上到下,逐一解析。

当走到输入a的时候,会将其压入调用栈中(call stack),然后去执行,执行完毕后,再将其从调用栈中移除。

走到定时器的时候,会将其先放入一个异步队列(callback queue),等待同步执行完毕后,再将其压入调用栈执行,所以计时器这块就暂时被挂起,优先输出了下面的b。

输出b的内容完毕后,调用栈清除后发现已经没有内容了。这个时候,调用栈就会去取异步队列的内容去执行。然后输出了c。

function test() {
  setTimeout(() => console.log(4));
  new Promise(resolve => {
    resolve();
    console.log(1);
  }).then(_ => {
    console.log(3);
  });
  console.log(2);
}

这个例子就是宏任务和微任务的优先级

setTimeout由于是异步,js优先将其挂起,压入callback queue中  ,setTimeout为宏任务挂载到宏任务队列中

new Promise的时候是马上去进行new了一个新对象,为同步代码,优先执行。输出1.此时.then方法为微任务挂载到微任务队列中。

然后继续执行同步代码,输出2.

此时调用栈的内容都执行完毕了,他现在要做的就是要把异步队列中的任务取过来运行。此时我们现在有两个异步队列,分别是宏任务队列中的setTimeout,微任务队列中的.then。微任务的执行顺序是优先与宏任务的。

所以把微任务队列中then方法压入了调用栈执行,输出为3.

微任务执行后,调用栈又没东西了,然后去看宏任务队列中还有没有要执行的。发现宏任务队列中有setTimeout。所以再把setTimeout取过来,压入调用栈执行,输出为4.

为什么说这个是浏览器的事件循环机制,因为js在执行的过程中,先优先执行同步代码。执行完后在去异步队列中看看有没有要执行的,处于一直在轮训的过程中。

DOM是在何时进行渲染的

还是因为js是单线程的,所以在js执行完同步代码后,也会优先去渲染dom,此时是不会去取异步队列的内容执行的。因为渲染的速度也是很快的,然后从感官上不会有因为异步任务而导致页面出现问题的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值