javascript运行时不管理任务源,仅提供事件循环和宏/微任务队列;任务按类型和插入时机入队,由宿主环境api决定来源,开发者需通过并发控制、promise链、queuemicrotask等协调优先级与依赖。

任务按类型分两层排队
所有异步操作最终都归为两类:
-
宏任务(Macrotask):包括
setTimeout、setInterval、I/O 回调、UI 渲染、postMessage、Worker.postMessage等。每次事件循环只取一个宏任务执行。 -
微任务(Microtask):包括
Promise.then/catch/finally、queueMicrotask、MutationObserver等。宏任务执行完后,会清空整个微任务队列(不是只取一个)。
不同 API 注册的任务,走不同路径但最终汇入队列
虽然来源不同,但它们都遵循同一套注入规则:
-
fetch()完成后,解析响应体并触发then—— 这个回调被当作微任务入队; -
setTimeout(fn, 0)到时后,fn被作为宏任务入队; -
new Promise(resolve => resolve())立即 resolve,其then回调立刻进微任务队列; - Web Worker 通过
postMessage发送消息,主线程收到后触发message事件 —— 这属于宏任务。
运行时不区分“任务源”,但开发者可以主动隔离与协调
当项目中存在多个独立异步模块(如 API 请求、WebSocket 心跳、本地缓存同步、定时上报),运行时不会自动识别它们的优先级或依赖关系。这时需要靠代码层面做协调:
- 用 并发控制器(如
ConcurrencyController类)限制某类任务(如接口请求)的最大并行数; - 用 Promise 链或 async/await 显式串行化有依赖的任务;
- 对高优任务(如用户操作反馈)使用
queueMicrotask插入微任务队列,确保比宏任务更早执行; - 对低频后台任务(如日志聚合)可延迟到下一个宏任务,或用
requestIdleCallback在浏览器空闲时执行。
多数据源场景需额外抽象层
像 Orbit.js 这样的框架,会在运行时之上构建协调器(Coordinator),把不同来源(API、IndexedDB、内存缓存)的操作封装成标准化的“操作指令”(Operation),再通过策略(Strategy)定义同步顺序和冲突规则。这层不是运行时的一部分,而是应用逻辑对任务流的再组织。
不复杂但容易忽略Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











