七個(gè)代替 setTimeout 的方案,讓定時(shí)任務(wù)更可靠
setTimeout是我們經(jīng)常使用的定時(shí)器API,它允許我們延遲執(zhí)行代碼。但在實(shí)際應(yīng)用中,setTimeout存在一些局限性和潛在問題,比如精度不高、在頁(yè)面不活躍時(shí)可能被節(jié)流等。分享7種替代方案,讓我們的定時(shí)任務(wù)更加可靠和高效。
1. requestAnimationFrame
requestAnimationFrame主要用于執(zhí)行動(dòng)畫,它會(huì)在瀏覽器下一次重繪之前調(diào)用指定的回調(diào)函數(shù)。
function animateWithRAF(timestamp) {
// 執(zhí)行動(dòng)畫邏輯
requestAnimationFrame(animateWithRAF);
}
requestAnimationFrame(animateWithRAF);
優(yōu)點(diǎn):
- 與顯示器刷新率同步,通常為60fps
- 在不可見標(biāo)簽頁(yè)中會(huì)暫停,節(jié)省資源
- 動(dòng)畫更平滑
2. setInterval + clearInterval
對(duì)于需要重復(fù)執(zhí)行的任務(wù),setInterval比多個(gè)setTimeout更合適。
const intervalId = setInterval(() => {
console.log("每秒執(zhí)行一次");
}, 1000);
// 停止定時(shí)器
// clearInterval(intervalId);
優(yōu)點(diǎn):
代碼更簡(jiǎn)潔
更適合固定間隔的重復(fù)任務(wù)
3. requestIdleCallback
當(dāng)瀏覽器空閑時(shí)執(zhí)行低優(yōu)先級(jí)任務(wù),避免影響關(guān)鍵操作。
優(yōu)點(diǎn):
- 充分利用瀏覽器空閑時(shí)間
- 可以設(shè)置超時(shí)保證任務(wù)最終會(huì)執(zhí)行
- 不阻塞主線程關(guān)鍵操作
4. Web Workers
將耗時(shí)任務(wù)移至后臺(tái)線程,避免阻塞主線程。
優(yōu)點(diǎn):
- 不阻塞UI線程
- 即使頁(yè)面不活躍也能繼續(xù)執(zhí)行
- 適合計(jì)算密集型任務(wù)
5. Promise + async/await
用Promise包裝setTimeout,結(jié)合async/await使異步代碼更清晰。
優(yōu)點(diǎn):
- 代碼更清晰,避免回調(diào)地獄
- 更好的錯(cuò)誤處理
- 便于鏈?zhǔn)浇M合多個(gè)異步操作
6. Web Animations API
對(duì)于動(dòng)畫效果,Web Animations API提供了更高級(jí)的控制。
優(yōu)點(diǎn):
- 聲明式API,更易于理解
- 內(nèi)置的暫停、恢復(fù)和控制功能
- 比CSS動(dòng)畫和setTimeout更精確
7. Intersection Observer
當(dāng)元素進(jìn)入視口時(shí)執(zhí)行代碼,比如延遲加載資源或觸發(fā)動(dòng)畫。
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log("元素進(jìn)入視口");
// 執(zhí)行需要的操作
}
});
});
observer.observe(document.querySelector('.lazy-load'));
優(yōu)點(diǎn):
- 無(wú)需手動(dòng)計(jì)算元素位置
- 性能更好,避免滾動(dòng)事件中大量計(jì)算
- 適合實(shí)現(xiàn)"按需執(zhí)行"的場(chǎng)景