# 怎么优化长任务
# 前提
- 浏览器主线程在执行完一个完整的js任务,才会去执行下一个
- performance 可以看到有哪些长任务
# 任务管理策略
# 拆分伪多个小任务
function saveSettings () {
validateForm();
showSpinner();
saveToDatabase();
updateUI();
sendAnalytics();
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 用异步操作延迟任务执行
- setTimeout(()=>{},0);
- async + setTimeout
function yieldToMain () {
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
1
2
3
4
5
2
3
4
5
# 使用 requestIdleCallback
- 有可能会导致永远执行不到
# 只在用户操作的时候让步
isInputPending
async function saveSettings () {
// 函数队列
const tasks = [validateForm,showSpinner,saveToDatabase,updateUI,sendAnalytics ];
while (tasks.length > 0) {
// 让步于用户输入
if (navigator.scheduling.isInputPending()) {
// 如果有用户输入在等待,则让步
await yieldToMain();
} else {
// Shift the the task out of the queue:
const task = tasks.shift();
// Run the task:
task();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# postTask
- 兼容性差,safari 完全不支持
- postTask并不是所有浏览器都支持。可以检测是否空,或者考虑使用polyfill。
# 使用web worker
- 主要用在计数型的需求,计算完成回传浏览器