JavaScript 运行机制详解(宏任务与微任务的解读 eventLoop)

本文深入剖析JavaScript的单线程特性,解释为何JS采用单线程,并探讨任务队列、事件循环机制。揭示宏任务与微任务的区别及执行流程,通过实例加深理解。

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

JavaScript 运行机制详解(宏任务与微任务的解读 eventLoop)

前言

1. 为什么JavaScript是单线程?
2. 任务队列
3. 微任务,宏任务

一、为什么JavaScript是单线程?

js是单线程的,也就代表js只能一件事情一件事情执行,那如果一件事情执行时间太久,后面要执行的就需要等待,需要等前面的事情执行完成,后面的才会执行。

二、任务队列
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着

如JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务,另一种是异步任务。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

*事件循环(Event Loop)

  1. -主线程先判断任务类型
    -1.如果是同步任务,主线程自己执行
    -2.如果是异步任务,交给宿主环境(浏览器)执行
(2)主线程之外,还存在一个"任务队列"(task queue)。每个异步执行完后,会将回调放进任务队列,先执行完成的先放进任务队列,依次放入。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",会取任务队列中的任务,由于任务队列里是依次放入进来的,所以取得时候也会先取先进来的,也就是先进先出原则。
(4)主线程不断重复上面的第三步。

如图展示
在这里插入图片描述

三,微任务,宏任务

微任务与宏任务

概念:

宿主环境提供的叫宏任务,由语言标准提供的叫微任务

  • 宿主环境:
    简单来说就是能使javascript完美运行的环境,只要能完美运行javascript的载体就是javascript的宿主环境。目前我们常见的两种宿主环境有浏览器和node。
    我们都知道window是我们一直使用的全局对象,但其实global 是 javascript
    运行时所在宿主环境提供的全局对象
    宿主环境内所有的内建或自定义的变量/函数都是 global/window 这个全局对象的属性/方法,而由宿主环境提供的也叫宏任务。

  • 语言标准:
    我们都知道JavaScript是一种编程语言,但其实JavaScript由ECMA制定标准,称之为ECMAScript,所以由语言标准提供的就是微任务,比如ES6提供的promise。
    promise是ES6语言标准提供的,定时器是宿主环境提供的,所以promise会比定时器更早执行。

常见宏任务与微任务
宏任务

宏任务

  • setTimeout记住这两个就好)

  • setInterval (记住这两个就好)


  • setImmediate(Node环境下独有)
  • requestAnimationFrame(浏览器环境独有)
  • I/O
  • UI rendering(浏览器独有)

微任务
微任务,

  • Promise.then()


  • Object.observe
  • MutationObserver
  • process.nextTick(Node环境独有)

微任务和宏任务的工作流程总结:有微则微,无微则宏)
在这里插入图片描述

先执行宏任务

  1. 宏任务执行完后
  2. 看微任务队列是否有微任务
  3. 没有微任务执行下一个宏任务
  4. 有微任务将所有微任务执行
  5. 执行完微任务,执行下一个宏任务

4.理解理论,做这套面试题再进一步理解

console.log(1)
setTimeout(function(){
  console.log(2)
}, 0)
new Promise(function(resolve){
  console.log(3)
  resolve()
}).then(function(){
  console.log(4)
})
console.log(5)

答案:1、3、5、4、2

// 请将下面这段代码的执行结果写出来
	async function async1() {
      console.log('async1 start')
      await async2()
      console.log('async1 end')
    }
    
    async function async2() {
      console.log('async2')
    }
    
    console.log('script start')

    setTimeout(function () {
      console.log('setTimeout')
    }, 0)

    async1();

    new Promise(function (resolve) {
      console.log('promise1')
      resolve();
    }).then(function () {
      console.log('promise2')
    })

    console.log('script end')

这段代码的执行结果会是什么呢?

知识点

解析:
1.await 执行完后,。async 标记的函数会返回一个 Promise 对象,等promise对面都执行完后再执行下面的语句**

2.await asyn2()后面的代码console.log(")相当于.then的微任务

最终答案为
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值