2.5 KiB
2.5 KiB
title, impact, impactDescription, tags
| title | impact | impactDescription | tags |
|---|---|---|---|
| 使用 requestIdleCallback 延迟非关键任务 | MEDIUM | 在后台任务期间保持 UI 响应 | javascript, performance, idle, scheduling, analytics |
使用 requestIdleCallback 延迟非关键任务
影响等级:中等(在后台任务期间保持 UI 响应)
使用 requestIdleCallback() 在浏览器空闲时段调度非关键任务。这能让主线程腾出来处理用户交互和动画,减少卡顿,提升感知性能。
不正确的做法(在用户交互期间阻塞主线程):
function handleSearch(query: string) {
const results = searchItems(query)
setResults(results)
// 这些操作会立即阻塞主线程
analytics.track('search', { query })
saveToRecentSearches(query)
prefetchTopResults(results.slice(0, 3))
}
正确的做法(将非关键任务推迟到空闲时间):
function handleSearch(query: string) {
const results = searchItems(query)
setResults(results)
// 将非关键任务推迟到空闲时段
requestIdleCallback(() => {
analytics.track('search', { query })
})
requestIdleCallback(() => {
saveToRecentSearches(query)
})
requestIdleCallback(() => {
prefetchTopResults(results.slice(0, 3))
})
}
为必须执行的任务设置超时:
// 确保分析事件在 2 秒内触发,即使浏览器一直繁忙
requestIdleCallback(
() => analytics.track('page_view', { path: location.pathname }),
{ timeout: 2000 }
)
将大任务分块处理:
function processLargeDataset(items: Item[]) {
let index = 0
function processChunk(deadline: IdleDeadline) {
// 在空闲时间内处理任务(目标:每块 < 50ms)
while (index < items.length && deadline.timeRemaining() > 0) {
processItem(items[index])
index++
}
// 如果还有剩余任务,调度下一块
if (index < items.length) {
requestIdleCallback(processChunk)
}
}
requestIdleCallback(processChunk)
}
为不支持的浏览器提供降级方案:
const scheduleIdleWork = window.requestIdleCallback ?? ((cb: () => void) => setTimeout(cb, 1))
scheduleIdleWork(() => {
// 非关键任务
})
适用场景:
- 分析与遥测
- 将状态保存到 localStorage/IndexedDB
- 为可能的下一个操作预取资源
- 处理非紧急的数据转换
- 非关键功能的懒初始化
不适用场景:
- 需要即时反馈的用户操作
- 用户正在等待的渲染更新
- 时间敏感的操作