promise鏈式調用通過.then()返回新promise實現異步順序執行,錯誤使用.catch()捕獲并置于鏈末尾確保全局捕獲;async/await以同步方式簡化異步代碼,用try/catch處理錯誤;promise.all適用于并行任務全成功才繼續,而promise.race用于響應首個完成的任務。例如鏈式調用中每個.then()返回新promise決定后續狀態,錯誤在.catch()中集中處理;async函數內用await等待異步結果,結構更清晰;promise.all接收多個promise數組并等全部成功或任一失敗,promise.race則取最快完成的結果。
異步 Promise 鏈式調用,簡單來說,就是讓一堆需要按順序執行的異步操作,像鏈條一樣一個接一個地執行,避免回調地獄,讓代碼更清晰易懂。
Promise 鏈式調用,讓異步操作更像同步代碼,可讀性更高,也更容易維護。
Promise 鏈的本質是,每個.then()方法都會返回一個新的 Promise 對象。這個新的 Promise 對象的狀態,取決于.then()中回調函數的返回值。如果回調函數返回一個 Promise,那么新的 Promise 的狀態就會和這個返回的 Promise 的狀態保持一致;如果回調函數返回一個普通值,那么新的 Promise 的狀態就會變成 resolved,并且這個返回值會作為下一個.then()方法的回調函數的參數。
function asyncTask(value) { return new Promise((resolve, reject) => { setTimeout(() => { const result = value * 2; console.log(`Task completed with result: ${result}`); resolve(result); //reject('Something went wrong'); // 模擬錯誤 }, 500); }); } asyncTask(5) .then(result => { console.log('First then:', result); return asyncTask(result); // 返回一個新的Promise }) .then(result => { console.log('Second then:', result); return asyncTask(result); // 再次返回一個新的Promise }) .then(result => { console.log('Third then:', result); return "Finished!"; }) .then(finalResult => { console.log('Final result:', finalResult); }) .catch(error => { console.error('Error occurred:', error); }) .finally(() => { console.log('Chain completed'); });
如何處理 Promise 鏈中的錯誤?
Promise 鏈中的錯誤處理,主要依賴.catch()方法。.catch()方法會捕獲鏈中任何一個 Promise 的 reject 狀態。這意味著,如果鏈中任何一個 Promise 拋出錯誤,.catch()方法就會被調用。需要注意的是,.catch()方法只會捕獲它之前的 Promise 的錯誤。如果想要處理整個鏈的錯誤,應該在鏈的末尾添加.catch()方法。
asyncTask(5) .then(result => { console.log('First then:', result); return asyncTask(result); }) .then(result => { console.log('Second then:', result); throw new Error("Simulated error in second then"); // 模擬錯誤 return asyncTask(result); }) .then(result => { console.log('Third then:', result); return "Finished!"; }) .then(finalResult => { console.log('Final result:', finalResult); }) .catch(error => { console.error('Error occurred:', error); // 這里會捕獲到 "Simulated error in second then" }) .finally(() => { console.log('Chain completed'); });
Async/Await 如何簡化 Promise 鏈?
Async/Await 是 ES2017 引入的語法糖,可以更簡潔地處理 Promise。使用 Async/Await 可以讓異步代碼看起來更像同步代碼,從而提高代碼的可讀性和可維護性。Async 函數會隱式地返回一個 Promise,而 Await 關鍵字會暫停 Async 函數的執行,直到 Promise 的狀態變成 resolved。
async function runTasks() { try { let result = await asyncTask(5); console.log('First result:', result); result = await asyncTask(result); console.log('Second result:', result); result = await asyncTask(result); console.log('Third result:', result); console.log('Finished!'); } catch (error) { console.error('Error occurred:', error); } finally { console.log('Tasks completed'); } } runTasks();
Async/Await 實際上是 Promise 的語法糖,底層依然是 Promise。使用 Async/Await 可以避免.then()方法的嵌套,讓代碼更易于理解。Async/Await 的錯誤處理使用 try…catch 語句,也比 Promise 的.catch()方法更直觀。
Promise.all 和 Promise.race 的應用場景
Promise.all 和 Promise.race 是處理多個 Promise 的工具函數。Promise.all 接收一個 Promise 數組,并返回一個新的 Promise。這個新的 Promise 會在所有 Promise 都變成 resolved 狀態時變成 resolved,或者在任何一個 Promise 變成 rejected 狀態時變成 rejected。Promise.race 也接收一個 Promise 數組,并返回一個新的 Promise。這個新的 Promise 會在第一個 Promise 變成 resolved 或 rejected 狀態時,就立即變成對應的狀態。
- Promise.all: 適合處理需要并行執行的異步操作,例如同時請求多個 API 接口,等待所有接口都返回數據后,再進行下一步處理。
const promise1 = asyncTask(5); const promise2 = asyncTask(10); const promise3 = asyncTask(15); Promise.all([promise1, promise2, promise3]) .then(results => { console.log('All results:', results); // [10, 20, 30] }) .catch(error => { console.error('Error occurred:', error); });
- Promise.race: 適合處理競態條件,例如設置一個超時時間,如果異步操作在超時時間內沒有完成,就認為操作失敗。
const promise = asyncTask(5); const timeout = new Promise((resolve, reject) => { setTimeout(() => { reject('Timeout'); }, 1000); }); Promise.race([promise, timeout]) .then(result => { console.log('Result:', result); // 如果 promise 在 1 秒內完成,則輸出結果 }) .catch(error => { console.error('Error occurred:', error); // 如果超時,則輸出 'Timeout' });
選擇使用 Promise.all 還是 Promise.race,取決于具體的業務場景。如果需要等待所有異步操作都完成,就使用 Promise.all;如果只需要等待第一個異步操作完成,或者需要處理競態條件,就使用 Promise.race。