js异步任务你都知道了吗?

在 JavaScript 中,queueMicrotaskscheduler.yieldscheduler.postTask都是用于控制代码执行时机的 API,它们在任务调度优先级和使用场景上有明显区别。以下是它们的详细对比和使用示例:

1. queueMicrotask - 微任务调度

  • 作用:将回调函数添加到当前微任务队列的末尾
  • 优先级 :高于所有宏任务(setTimeoutrequestAnimationFrame等),在当前同步代码执行完成后立即执行
  • 适用场景:需要在当前事件循环的同步代码执行完毕后,且在宏任务执行前完成的操作
js 复制代码
console.log("同步代码开始");

// 宏任务
setTimeout(() => {
  console.log("setTimeout宏任务执行");
}, 0);

// 微任务 - queueMicrotask
queueMicrotask(() => {
  console.log("第一个queueMicrotask执行");
  
  // 嵌套的微任务会继续加入当前微任务队列
  queueMicrotask(() => {
    console.log("嵌套的queueMicrotask执行");
  });
});

// Promise.then也是微任务,与queueMicrotask优先级相同
Promise.resolve().then(() => {
  console.log("Promise.then微任务执行");
});

console.log("同步代码结束");

// 输出顺序:
// 同步代码开始
// 同步代码结束
// 第一个queueMicrotask执行
// Promise.then微任务执行
// 嵌套的queueMicrotask执行
// setTimeout宏任务执行

特点

  • Promise.then同属微任务队列,执行顺序由添加顺序决定
  • 无延迟控制,会在当前同步流程结束后立即执行
  • 适合做一些轻量的后续处理,避免阻塞 UI

2. scheduler.yield - 让出主线程(实验性)

  • 作用:暂停当前任务,允许浏览器处理其他高优先级任务(如用户输入、渲染)后再继续
  • 优先级:低于微任务,高于普通宏任务,本质是创建一个低优先级的宏任务
  • 适用场景:长时间运行的任务需要分段执行,避免阻塞 UI 响应
js 复制代码
// 注意:需要浏览器支持Scheduler API(如Chrome 88+)
async function processLargeData(items) {
  for (const item of items) {
    // 处理单个项目(轻量操作)
    console.log(`处理项目: ${item}`);
    
    // 每处理3个项目,让出主线程一次
    if (items.indexOf(item) % 3 === 0 && items.indexOf(item) !== 0) {
      console.log("让出主线程...");
      await scheduler.yield(); // 暂停并允许浏览器处理其他任务
    }
  }
  console.log("所有项目处理完成");
}

// 模拟大量数据处理
processLargeData([1, 2, 3, 4, 5, 6, 7, 8, 9]);

// 同时模拟用户输入处理(高优先级)
document.addEventListener("click", () => {
  console.log("用户点击事件被处理");
});

// 输出顺序(可能因浏览器调度略有差异):
// 处理项目: 1
// 处理项目: 2
// 处理项目: 3
// 让出主线程...
// 处理项目: 4
// 处理项目: 5
// 处理项目: 6
// 让出主线程...
// (如果此时有点击,会插入"用户点击事件被处理")
// 处理项目: 7
// ...

特点

  • 属于实验性 API,需通过window.scheduler访问,兼容性有限(主要支持 Chrome)
  • 本质是返回一个 Promise,当浏览器准备好继续执行时 resolve
  • 适合长时间运行的计算任务分段执行,保证 UI 响应性

3. scheduler.postTask - 优先级任务调度(实验性)

  • 作用:将任务添加到调度队列,并指定优先级(高 / 中 / 低)
  • 优先级:可以控制任务执行的相对顺序,高优先级任务先于低优先级执行
  • 适用场景:需要按重要性区分执行顺序的任务,如紧急更新 vs 后台计算
js 复制代码
// 注意:需要浏览器支持Scheduler API
async function demoPostTask() {
  // 高优先级任务
  scheduler.postTask(() => {
    console.log("高优先级任务执行 - 紧急更新");
  }, { priority: 'user-blocking' }); // 最高优先级

  // 中优先级任务(默认)
  scheduler.postTask(() => {
    console.log("中优先级任务执行 - 普通操作");
  }); // 默认priority: 'user-visible'

  // 低优先级任务
  scheduler.postTask(() => {
    console.log("低优先级任务执行 - 后台计算");
  }, { priority: 'background' });

  // 延迟执行的高优先级任务
  scheduler.postTask(() => {
    console.log("延迟的高优先级任务");
  }, { priority: 'user-blocking', delay: 100 });
}

demoPostTask();

// 输出顺序(通常):
// 高优先级任务执行 - 紧急更新
// 中优先级任务执行 - 普通操作
// 低优先级任务执行 - 后台计算
// 延迟的高优先级任务

特点

  • 支持三种优先级:user-blocking(最高,阻塞用户操作)、user-visible(默认,影响用户可见内容)、background(最低,后台任务)
  • 可以设置delay延迟执行,类似setTimeout但带有优先级控制
  • 实验性 API,主要支持 Chrome,生产环境需谨慎使用

三者核心区别对比

特性 queueMicrotask scheduler.yield scheduler.postTask
任务类型 微任务 低优先级宏任务 可指定优先级的宏任务
优先级 最高(同步后立即执行) 中(允许浏览器处理其他任务) 可设置(高 / 中 / 低)
阻塞 UI 可能(微任务过多会阻塞) 不会(主动让出主线程) 低优先级任务不会阻塞
适用场景 同步后的收尾操作 长任务分段执行 按重要性调度任务
兼容性 所有现代浏览器 仅 Chrome 等部分浏览器 仅 Chrome 等部分浏览器
延迟控制 无(立即让出) 支持delay参数

实际应用建议

  1. 普通微任务需求 :优先使用queueMicrotask(兼容性好)
  2. 长任务拆分 :使用scheduler.yield(需处理兼容性)
  3. 任务优先级控制 :使用scheduler.postTask(适合实验性或 Chrome 专用场景)
  4. 生产环境:对于实验性 API,建议使用特性检测并提供降级方案:
javascript 复制代码
// 特性检测示例
if (window.scheduler && scheduler.postTask) {
  // 使用scheduler.postTask
} else {
  // 降级为setTimeout
  setTimeout(() => { /* 任务 */ }, 0);
}

这些 API 共同丰富了 JavaScript 的任务调度能力,使开发者能更精细地控制代码执行时机,优化应用性能和用户体验。

相关推荐
光影少年2 小时前
react生态
前端·react.js·前端框架
golang学习记3 小时前
从0死磕全栈之Next.js 中的错误处理机制详解(App Router)
前端
力Mer3 小时前
console.log()控制台异步打印与对象展开后不一致问题
前端·javascript
绝无仅有3 小时前
数据库mysql报错追踪与解决总结
后端·面试·github
WillaWang3 小时前
Liquid:在assign定义变量时使用allow_false
前端
2401_831501733 小时前
Python学习之Day05学习(定制数据对象,面向对象)
前端·python·学习
GISer_Jing3 小时前
得物前端二面潜在问题详解
前端·javascript·面试
飞天巨兽4 小时前
HTTP基础教程详解
前端·网络·网络协议·http
FIN66684 小时前
昂瑞微IPO前瞻:技术破局高端射频模组,国产替代第二波浪潮下的硬科技突围
前端·科技·搜索引擎·产品运营·创业创新·制造·射频工程