JavaScript Event Loop机制详解:宏任务与微任务的执行顺序

作者:异步漫步时间:2026-10-23 20:23:51浏览:133

本文深入解析JavaScript单线程模型下的Event Loop机制,详细区分宏任务(Macro-task)与微任务(Micro-task)的定义与执行时机。通过具体代码示例,阐明同步代码、异步微任务及宏任务的执行优先级,解释为何await后的代码与Promise会在定时器之前执行,帮助开发者掌握异步编程的核心逻辑。

JavaScript Event Loop机制详解:宏任务与微任务的执行顺序

首先观察以下代码片段:


async function (){
		await f2()
		console.log('f1')
	}

	async function f2(){
		console.log('f2')
	}
	
	console.log('正常1')
	f1()
	setTimeout(()=>{
		console.log('定时器')
	})
	console.log('正常2')

该段代码预期的正确输出顺序依次为:正常1、f2、正常2、f1、定时器。

造成上述输出顺序的原因是什么?

JavaScript单线程模型与任务分类

JavaScript是一门单线程语言,尽管HTML5引入了Web-Worker,但JavaScript核心的单线程特性并未改变。由于是单线程执行,其运行模式类似于只有一个窗口的银行,客户必须排队依次办理业务,同理JavaScript的任务也必须按顺序逐一执行。若某个任务耗时过长,后续任务将被阻塞等待,因此产生了同步任务与异步任务的区分。

基本概念

除了广义的同步与异步任务概念外,对任务类型可进行更细致的分类。

  • 宏任务(macro-task):包括整体代码script、setTimeout、setInterval。
  • 微任务(micro-task):包括Promise、process.nextTick。

宏任务执行机制:浏览器为了确保JS内部的task与DOM任务有序执行,会在一个task执行结束后、下一个task执行开始前,对页面进行重新渲染(即task->渲染->task的循环过程)。

例如,鼠标点击触发事件回调需要执行一个宏任务,随后解析HTML。

微任务机制:微任务通常指在当前同步任务执行结束后立即执行的任务,例如对一系列动作做出反馈,或执行无需分配新任务的异步操作,以此降低性能开销。

明确概念后,我们再次分析代码的执行流程。


async function (){
		await f2()
		console.log('f1')
	}

	async function f2(){
		console.log('f2')
	}
	
	console.log('正常1')
	f1()
	setTimeout(()=>{
		console.log('定时器')
	})
	console.log('正常2')

代码执行流程与输出顺序解析

执行流程分析

首先执行正常的同步流程,打印出“正常1”。接着执行f1()函数,由于f1内部包含await,await后面的f2()会立即执行,因此打印“f2”。随后继续执行同步代码,打印“正常2”。此时同步任务全部结束,开始执行异步队列中的微任务。await f2()等待f2()方法执行完毕后,继续执行后续代码打印“f1”。最后执行宏任务队列中的setTimeout,打印“定时器”。

这就是“正常1”和“正常2”打印在“f1”之前的原因,因为所有微任务执行时,当前执行栈的代码必须已执行完毕。而“f2”和“f1”打印在“定时器”之前,是因为所有微任务总会在下一个宏任务之前全部执行完毕。

以上为本文的全部内容,希望对您的学习有所帮助,也欢迎大家继续支持本站。

作者最新文章