Web前端入门第 68 问:JavaScript 事件循环机制中的微任务与宏任务
JS 是单线程语言。这句话对不对?
按照目前的情况来看,JS 自从支持了 Web Worker
之后,就不再是单线程语言了,但 Worker 的工作线程与主线程有区别,在 Worker 的工作线程中无法直接操作 DOM、window 对象或大多数浏览器 API(如 localStorage),Worker 的全局对象也不再是 window 对象,而是 self。
Worker 中的事件循环与主线程相互独立,互不影响,但执行顺序还是得遵循 JS 的语法规则。
宏任务
宏任务表示执行时间较长的任务,在每次时间循环时只会执行一个宏任务,执行完毕后处理微任务队列,所有微任务都执行完毕后进入下一个宏任务。
JS 常见宏任务类型:
- 定时器任务:setTimeout / setInterval
- DOM 事件回调(如 click、scroll)
- I/O 操作(如文件读取、网络请求)
- 浏览器用于执行动画的方法
requestAnimationFrame
,执行时机与渲染相关 - Node.js 环境的
setImmediate
- script 标签内主线程的同步代码(整体作为一个宏任务)
微任务
微任务表示更轻量的异步任务,当宏任务执行完毕之后立即执行。
JS 常见微任务类型:
Promise.then()
/Promise.catch()
/Promise.finally()
- 浏览器监听 DOM 变化的 API 对象,比如:
MutationObserver
- 手动添加微任务API方法:
queueMicrotask()
- nodejs 中的
process.nextTick()
代码解析
看这么一段代码:
(function() {
console.log(1)
setTimeout(() => { console.log(2); });
queueMicrotask(() => console.log(3))
new Promise(resolve => {
console.log(4);
setTimeout(() => {
resolve();
console.log(5);
}, 0);
Promise.resolve().then(() => console.log(6));
console.log(7);
}).then(() => {
console.log(8);
Promise.resolve().then(() => console.log(9));
});
console.log(10);
})();
分析代码:
(function() {
console.log(1) // 同步任务
setTimeout(() => { console.log(2); });
queueMicrotask(() => console.log(3))
new Promise(resolve => {
console.log(4); // 同步任务
setTimeout(() => { // 宏任务
resolve(); // 宏任务的同步任务
console.log(5); // 宏任务中的同步任务
}, 0);
Promise.resolve().then(() => console.log(6)); // 微任务
console.log(7); // 同步任务
}).then(() => { // 微任务
console.log(8); // 微任务中的同步任务
Promise.resolve().then(() => console.log(9)); // 微任务中的微任务
});
console.log(10); // 同步任务
})();
第一轮
首先同步代码的宏任务优先级最高,不管微任务还是宏任务,同步代码都会先执行。
所以上面代码会优先执行:
console.log(1)
console.log(4);
console.log(7);
console.log(10);
接着开始处理微任务:
queueMicrotask(() => console.log(3))
Promise.resolve().then(() => console.log(6));
微任务处理完,开始执行下一轮宏任务。
第二轮
这一轮中的宏任务只有一个 setTimeout,执行完之后由于没有微任务队列,所以直接执行下一轮宏任务。
setTimeout(() => { console.log(2); });
第三轮
这一轮的宏任务中有同步代码。
setTimeout(() => { // 宏任务
resolve(); // 宏任务的同步任务
console.log(5); // 宏任务中的同步任务
}, 0);
在执行完 resolve()
之后,会将 Promise.then 的回调函数放入微任务队列中,所以在宏任务执行完之后会开始微任务:
then(() => { // 微任务
console.log(8); // 微任务中的同步任务
Promise.resolve().then(() => console.log(9)); // 微任务中的微任务
})
最终的打印顺序
1
4
7
10
3
6
2
5
8
9
执行流程图
JS 代码逐行执行,在遇到宏任务时,整个代码块丢到宏任务队列,在遇到微任务时,将微任务丢到本次事件循环中的微任务队列,本次事件循环执行完之后,再执行微任务队列中的任务,微任务执行完之后开始下一个宏任务执行。
JS 代码执行机制:
宏任务执行机制:
写在最后
JS 中的代码执行流程永远都是事件循环机制,这是 JS 的任务调度核心,理解事件循环机制,才能在开发中游刃有余~~
Web前端入门第 68 问:JavaScript 事件循环机制中的微任务与宏任务的更多相关文章
- 一篇文章图文并茂地带你轻松学完 JavaScript 事件循环机制(event loop)
JavaScript 事件循环机制 (event loop) 本篇文章已经默认你有了基础的 ES6 和 javascript语法 知识. 本篇文章比较细致,如果已经对同步异步,单线程等概念比较熟悉的读 ...
- 深入理解JavaScript事件循环机制
前言 众所周知,JavaScript 是一门单线程语言,虽然在 html5 中提出了 Web-Worker ,但这并未改变 JavaScript 是单线程这一核心.可看HTML规范中的这段话: To ...
- 深入浅出Javascript事件循环机制
一.JS单线程.异步.同步概念 众所周知,JS是单线程(如果一个线程删DOM,一个线程增DOM,浏览器傻逼了-所以只能单着了),虽然有webworker酱紫的多线程出现,但也是在主线程的控制下.web ...
- javascript事件循环机制 浅尝手记
引入 众所周知Javascript是一个单线程的机制,虽然可以依托多线程的浏览器实现页面如何实现页面复杂的渲染.事件响应,但仍不会改变其单线程的本质:所以对于js的事件循环机制的了解是一个前端人员的必 ...
- 浏览器中的JavaScript事件循环机制
浏览器的事件循环机制是HTML中定义的规范. JavaScript有一个主线程和调用栈,所有的任务都会被放到调用栈等待主线程执行. JS调用栈 是一种先进后出的数据结构.当函数被调用时,会被添加到栈中 ...
- javaScript 事件循环机制
JavaScript是单线程的编程语言,只能同一时间内做一件事.但是在遇到异步事件的时候,js线程并没有阻塞,还会继续执行,这就是因为JS有事件循环机制. 事件循环流程总结 主线程开始执行一段代码, ...
- JavaScript事件循环机制
事件循环 事件循环不仅仅包含事件队列,而是具有至少两个队列,除了事件,还要保持浏览器执行的其他操作.这些操作被称为任务,并且分为两类:宏任务(或通常称为任务)和微任务. 单次循环迭代中,最多处理一个宏 ...
- JS JavaScript事件循环机制
区分进程和线程 进程是cpu资源分配的最小单位(系统会给它分配内存) 不同的进程之间是可以同学的,如管道.FIFO(命名管道).消息队列 一个进程里有单个或多个线程 浏览器是多进程的,因为系统给它的进 ...
- 一道面试题引发对javascript事件循环机制(Event Loop)的 思考(这里讨论针对浏览器)
- JS浏览器事件循环机制
文章来自我的 github 博客,包括技术输出和学习笔记,欢迎star. 先来明白些概念性内容. 进程.线程 进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的. ...
随机推荐
- DEV插件--Spreadsheet1电子表格
常用操作Spreadsheet常用属性标题栏是否可见 Spreadsheet1.TitleBar.Visible=true标题栏背景颜色 Spreadsheet1.TitleBar.Interior. ...
- 网络编程-Netty-writeAndFlush方法原理分析 以及 close以后是否还能写入数据?
前言 在上一讲网络编程-关闭连接(2)-Java的NIO在关闭socket时,究竟用了哪个系统调用函数?中,我们做了个实验,研究了java nio的close函数究竟调用了哪个系统调用,答案是clos ...
- 【Maven】POM基本概念
目前的技术在开发中存在的问题: 一个项目就是一个工程 如果项目非常庞大,就不适合继续使用 package 来划分模块.最好是每一个模块对应一个工程,利于分工协作. 借助于 Maven 就可以将一个项目 ...
- 航天信息诺税通SAAS接口封装DLL
项目中需要对接航天信息的诺税通接口开具电子发票,为此将功能封装到了DLL中,其他项目也可以方便的引用. Delphi调用示例: 有需要可以和我联系:yzqnet(微信)
- FastAPI依赖注入作用域与生命周期控制
title: FastAPI依赖注入作用域与生命周期控制 date: 2025/04/08 00:02:10 updated: 2025/04/08 00:02:10 author: cmdragon ...
- shell子字符串截取
http://c.biancheng.net/view/1120.html Shell 截取字符串通常有两种方式:从指定位置开始截取和从指定字符(子字符串)开始截取. 从指定位置开始截取 这种方式需要 ...
- 华为od机考2025A卷真题 -补种未成活胡杨
题目描述与示例 题目描述 近些年来,我国防沙治沙取得显著成果.某沙漠新种植N棵胡杨(编号1-N),排成一排. 一个月后,有M棵胡杨未能成活. 现可补种胡杨K棵,请问如何补种(只能补种,不能新种) ,可 ...
- 为什么不推荐在 MySQL 中直接存储图片、音频、视频等大容量内容?
在MySQL中直接存储图片.音频.视频等大容量内容(通常称为BLOB数据)通常不被推荐,主要原因包括以下几点: 1. 性能问题 存储效率:存储大容量文件(如图片.音频.视频等)会大幅增加数据库的存储负 ...
- 智能语音备忘录:SpeechRecognition与gTTS的奇妙融合
引言:智能语音备忘录的时代已经到来 在这个信息爆炸的时代,我们每天需要处理大量的事务和信息.传统的文字记录方式虽然可靠,但在效率上往往难以满足快节奏生活的需求.想象一下,如果你能在驾车.散步或是灵感突 ...
- CF1424G题解
思路 这个题意思很显然,是求 nnn 个区间重叠最多的地方和值. 那么我们能想到用差分数组,在扫一遍的过程中维护最大值和 pospospos. 但是需要注意的是,区间最大会到 10910^9109,直 ...