Scheduler.yield() 是浏览器 Prioritized Task Scheduling API 中的异步方法,用于协作式让出主线程控制权,让浏览器优先处理用户输入、渲染等高优先级任务,避免长任务阻塞页面、导致卡顿(优化INP)。
- 语法:
await scheduler.yield() - 返回:Promise,resolve后继续执行后续代码
- 本质:把当前长任务拆分成多个小任务,让出后以user-visible默认优先级继续执行,不引入额外延迟(比setTimeout/requestIdleCallback更轻量)
二、核心特性
- 协作式让步,非强制:只是告诉调度器“我可以暂停”,调度器会先处理队列中更高优先级任务(如点击、滚动、渲染),再恢复当前任务;不会强制切换、不保证立即让出
- 优先级继承:在
Scheduler.postTask()回调中调用时,会继承该任务的优先级(user-blocking/user-visible/background) - 可取消:在
postTask()的AbortSignal关联任务中,可通过abort()取消yield后的续执行 - 浏览器支持:Chrome 124+、Edge 124+;Firefox/Safari暂未实现,需做兼容性检测
三、基础用法(拆分长任务)
// 检测兼容性
if ('scheduler'in navigator && 'yield'in scheduler) {
asyncfunction longTask() {
for (let i = 0; i < 10000; i++) {
// 每执行100次,让出主线程
if (i % 100 === 0) {
await scheduler.yield(); // 让出,等浏览器处理高优任务
}
// 执行耗时计算/渲染逻辑
computeHeavyWork(i);
}
}
longTask();
} else {
// 降级方案:用setTimeout模拟
asyncfunction longTaskFallback() {
for (let i = 0; i < 10000; i++) {
if (i % 100 === 0) {
awaitnewPromise(resolve => setTimeout(resolve, 0));
}
computeHeavyWork(i);
}
}
}
四、与常见方案对比
| 方案 | 核心区别 | 延迟 | 优先级 | 适用场景 |
|---|---|---|---|---|
| scheduler.yield() | 协作让出、续执行高优、无额外延迟 | 极小 | 可继承/默认user-visible | 长任务拆分、提升页面响应、优化INP |
| setTimeout(0) | 强制进入宏任务队列、延迟不确定 | 有(至少4ms) | 普通 | 兼容性兜底 |
| requestIdleCallback | 仅在浏览器空闲时执行、有deadline | 不确定 | 低 | 非紧急后台工作 |
五、关键注意事项
- 必须用await调用,否则不会让出主线程、直接同步执行
- 仅在主线程有效,Web Worker中无
scheduler对象 - 生产环境必须做兼容性判断,避免报错
- 不要过度调用:频繁yield会增加任务切换开销,反而降低性能