如果你也對異步 JavaScript 感到頭疼,不妨試試以下這 7 個(gè)簡單實(shí)用的技巧,它們可以讓你重新愛上這項(xiàng)技術(shù)!
1. 使用 Promise.allSettled()
進(jìn)行更安全的批量處理
當(dāng)你需要處理多個(gè) Promise 時(shí),Promise.all()
一旦遇到一個(gè)失敗的 Promise 就會終止整個(gè)操作。而 Promise.allSettled()
則會等待所有 Promise 都完成(無論成功還是失敗),并返回每個(gè) Promise 的狀態(tài)和值或錯(cuò)誤信息。
const results = await Promise.allSettled([
fetchData1(),
fetchData2(),
fetchData3(),
]);
results.forEach(result => {
if (result.status === 'fulfilled') {
console.log('成功:', result.value);
} else {
console.error('失敗:', result.reason);
}
});
通過這種方式,你可以安全地處理所有操作,而不用擔(dān)心單個(gè)失敗會影響整體流程。
2. 為 Promise 添加超時(shí)功能,防止卡死
有些 Promise 可能會因?yàn)榉N種原因長時(shí)間懸而未決,為它們添加一個(gè)超時(shí)限制可以保護(hù)你的應(yīng)用程序。
const withTimeout = (promise, ms) =>
Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('操作超時(shí)')), ms)
),
]);
try {
const data = await withTimeout(fetchData(), 5000);
} catch (err) {
console.error(err.message); // 如果超時(shí),將輸出 "操作超時(shí)"
}
通過這種方式,即使某個(gè)操作卡住,也不會拖累整個(gè)應(yīng)用。
3. 使用 for...of
實(shí)現(xiàn)順序異步循環(huán)
雖然 forEach()
是個(gè)好工具,但它不能很好地支持 async/await。使用 for...of
進(jìn)行順序異步操作更加直觀:
const urls = ['url1', 'url2', 'url3'];
for (const url of urls) {
const data = await fetch(url);
console.log(data);
}
這種方法可以確保每個(gè)請求依次執(zhí)行,而不會互相干擾。
4. 用 await 實(shí)現(xiàn)動態(tài)延時(shí)
在異步操作之間添加延時(shí),可以通過 await 實(shí)現(xiàn)簡單而優(yōu)雅的方式,而不會阻塞主線程:
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
console.log('開始');
await delay(2000); // 等待 2 秒
console.log('結(jié)束');
這種技巧在模擬異步環(huán)境或控制操作節(jié)奏時(shí)非常有用。
5. 在異步函數(shù)中始終使用 try...catch
即使在 async 函數(shù)中,也需要用 try...catch
來捕獲錯(cuò)誤。將其作為一種習(xí)慣,可以避免遺漏異常處理:
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('請求失敗');
return await response.json();
} catch (err) {
console.error('錯(cuò)誤:', err.message);
return null;
}
}
這樣可以確保函數(shù)的健壯性,即使請求失敗也能 gracefully 處理。
6. 在循環(huán)外使用 await
實(shí)現(xiàn)批量處理
如果操作不需要按順序執(zhí)行,可以通過批量處理提升性能:
const urls = ['url1', 'url2', 'url3'];
const responses = await Promise.all(urls.map(url => fetch(url)));
const data = await Promise.all(responses.map(res => res.json()));
console.log(data);
這種方法適合需要并行處理多個(gè)任務(wù)的場景,例如批量獲取數(shù)據(jù)。
7. 結(jié)合 Async/Await 和生成器處理復(fù)雜流程
生成器函數(shù)可以用作異步流程中的“檢查點(diǎn)”,讓復(fù)雜的邏輯變得更容易理解:
function* generator() {
yield fetchData1();
yield fetchData2();
yield fetchData3();
}
const runGenerator = async gen => {
const iterator = gen();
for (const promise of iterator) {
console.log(await promise);
}
};
await runGenerator(generator);
這種方式可以讓異步代碼的邏輯更加清晰,尤其是在需要分階段處理的場景下。
掌握這些技巧后,你會發(fā)現(xiàn)異步 JavaScript 不再難以駕馭。
該文章在 2025/1/22 10:01:25 編輯過