浏览器的宏任务(MacroTask)的优先级

#bom #浏览器

目录

1. 宏任务优先级从高到低排序

// 优先级从高到低
1. 用户交互事件(User Interaction)
   - 点击(click)
   - 输入(input)
   - 键盘事件(keyboard)
   - 触摸事件(touch)

2. 网络请求回调(Network)
   - fetch 回调
   - XMLHttpRequest 回调

3. 页面渲染事件(Rendering)
   - requestAnimationFrame
   - IntersectionObserver

4. setTimeout/setInterval
   - setTimeout(fn, 0) 实际最小延迟 4ms
   - setInterval 的回调

5. setImmediate(Node.js 环境)

6. MessageChannel

7. I/O 事件
   - 文件操作
   - IndexedDB

2. 具体示例

// 1. 用户点击事件优先级最高
button.addEventListener('click', () => {
    console.log('Click event');
});

// 2. 网络请求
fetch('/api/data').then(() => {
    console.log('Fetch callback');
});

// 3. 渲染
requestAnimationFrame(() => {
    console.log('Animation frame');
});

// 4. 定时器(较低优先级)
setTimeout(() => {
    console.log('Timeout');
}, 0);

3. 优先级影响因素

3.1. 任务类型

// 用户交互类型的任务优先级最高
element.addEventListener('click', () => {
    // 高优先级
    console.log('User interaction');
});

setTimeout(() => {
    // 低优先级
    console.log('Timer');
}, 0);

3.2. 浏览器调度策略

// 示例:页面性能优化
// 高优先级任务
document.addEventListener('click', () => {
    // 用户交互立即响应
    updateUI();
});

// 低优先级任务
setTimeout(() => {
    // 非关键操作延后执行
    analytics.send();
}, 0);

4. 实际应用场景

4.1. 性能优化

// 高优先级任务:关键渲染
requestAnimationFrame(() => {
    updateCriticalUI();
});

// 低优先级任务:数据统计
setTimeout(() => {
    sendAnalytics();
}, 0);

4.2. 用户体验优化

// 即时响应用户输入
input.addEventListener('input', (e) => {
    // 立即更新UI反馈
    updateSearchResults(e.target.value);
});

// 延迟处理非关键任务
setTimeout(() => {
    // 缓存搜索结果
    cacheResults();
}, 100);

4.3. 资源加载优化

// 优先加载关键资源
fetch('/critical-data.json')
    .then(handleCriticalData);

// 延迟加载非关键资源
setTimeout(() => {
    fetch('/non-critical-data.json')
        .then(handleNonCriticalData);
}, 1000);

5. 注意事项

5.1. 定时器延迟

// 最小延迟 4ms
setTimeout(() => {
    console.log('Delayed');
}, 0);  // 实际至少 4ms 后执行

5.2. 优先级保证

// 高优先级任务不应被低优先级任务阻塞
button.addEventListener('click', () => {
    // 重要的用户响应
    updateUI();
    
    // 非关键任务延后处理
    setTimeout(nonCriticalTask, 0);
});

5.3. 避免优先级反转

// 不好的做法
setTimeout(() => {
    // 关键任务不应放在低优先级队列
    criticalTask();
}, 0);

// 好的做法
requestAnimationFrame(() => {
    criticalTask();
});

6. 最佳实践

6.1. 任务分类

// 关键任务:用户交互、UI更新
function criticalTask() {
    // 直接执行
}

// 非关键任务:日志、统计
function nonCriticalTask() {
    setTimeout(() => {
        // 延迟执行
    }, 0);
}

6.2. 优先级管理

class TaskScheduler {
    static high(task) {
        requestAnimationFrame(task);
    }
    
    static low(task) {
        setTimeout(task, 0);
    }
}