promise & async await总结
优先使用 async/await 编写更清晰的代码合理使用 Promise 方法(如 all/race)处理并行任务不要忘记错误处理,使用 try/catch 或 .catch()避免不必要的 await,能并行就不要顺序执行注意 Promise 创建时机,避免意外提前执行。
·
一、Promise 核心概念
-
Promise 是什么?
Promise 是 JavaScript 中用于处理异步操作的对象
,它代表一个尚未完成但预期将来会完成的操作
。 -
Promise 的三种状态
- pending:初始状态,既不是成功也不是失败
- fulfilled:操作成功完成
- rejected:操作失败
-
创建 Promise
const myPromise = new Promise((resolve, reject) => { // 异步操作 if (/* 操作成功 */) { resolve('成功的结果'); } else { reject('失败的原因'); } });
-
Promise 方法链
myPromise .then(result => { console.log(result); // '成功的结果' return '新的值'; }) .then(newResult => { console.log(newResult); // '新的值' }) .catch(error => { console.error(error); // '失败的原因' }) .finally(() => { console.log('无论成功失败都会执行'); });
二、Promise 高级用法
-
Promise 静态方法
// 所有 Promise 都解决 Promise.all([promise1, promise2]) .then(values => console.log(values)); // 任意一个 Promise 解决 Promise.race([promise1, promise2]) .then(value => console.log(value)); // 所有 Promise 都完成(无论成功失败) Promise.allSettled([promise1, promise2]) .then(results => console.log(results)); // 立即返回一个已解决的 Promise Promise.resolve('立即解决'); Promise.reject('立即拒绝');
-
Promise 链式调用的错误处理
doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .catch(error => console.error(error)); // 捕获前面所有 then 中的错误
-
Promise 常见陷阱
// 错误示例:忘记返回 Promise doSomething() .then(result => { doSomethingElse(result); // 忘记 return }) .then(newResult => { // newResult 会是 undefined }); // 正确写法 doSomething() .then(result => { return doSomethingElse(result); // 显式返回 });
三、async/await 详解
-
async 函数
async function myAsyncFunction() { return 'Hello'; // 自动包装成 Promise } // 等同于 function myAsyncFunction() { return Promise.resolve('Hello'); }
-
await 表达式
async function fetchData() { try { const response = await fetch('api/data'); // 等待 Promise 解决 const data = await response.json(); // 再次等待 return data; } catch (error) { console.error('获取数据失败:', error); throw error; // 可以重新抛出错误 } }
-
async/await 错误处理
// 方法1:try/catch async function getUser() { try { const user = await fetchUser(); return user; } catch (error) { console.error('获取用户失败:', error); return null; } } // 方法2:catch 处理返回的 Promise async function getUser() { const user = await fetchUser().catch(error => { console.error('获取用户失败:', error); return null; }); return user; }
四、Promise 与 async/await 对比
-
代码风格对比
// Promise 风格 function getData() { return fetchData() .then(data => processData(data)) .then(result => saveResult(result)) .catch(error => handleError(error)); } // async/await 风格 async function getData() { try { const data = await fetchData(); const result = await processData(data); return await saveResult(result); } catch (error) { handleError(error); } }
-
何时使用哪种?
- 使用 Promise:
- 需要同时处理多个异步操作(Promise.all/race)
- 需要精细控制 Promise 链
- 简单的单次异步操作
- 使用 async/await:
- 需要顺序执行的异步操作
- 需要更清晰的错误处理
- 代码可读性更重要时
五、常见问题与最佳实践
-
避免 await 滥用
// 错误:不必要的顺序执行 async function processItems(items) { for (const item of items) { await processItem(item); // 每个都等待,效率低 } } // 正确:并行处理 async function processItems(items) { await Promise.all(items.map(item => processItem(item))); }
-
顶层 await
// 模块顶层可以使用 await const data = await fetchData(); console.log(data); // 注意:需要在 ES 模块中(type="module")
-
async 函数总是返回 Promise
async function foo() { return 'bar'; } console.log(foo()); // Promise {<fulfilled>: "bar"}
-
在循环中使用 await
// for...of 可以安全使用 await async function processArray(array) { for (const item of array) { await processItem(item); } } // 不要在 forEach 中使用 await array.forEach(async (item) => { await processItem(item); // 不会按预期工作 });
六、实际应用示例
-
带超时的 Promise
function fetchWithTimeout(url, timeout = 5000) { return Promise.race([ fetch(url), new Promise((_, reject) => setTimeout(() => reject(new Error('请求超时')), timeout) ) ]); }
-
顺序执行异步任务
async function executeSequentially(promises) { const results = []; for (const promise of promises) { results.push(await promise); } return results; }
-
重试机制
async function retry(fn, retries = 3, delay = 1000) { try { return await fn(); } catch (error) { if (retries <= 0) throw error; await new Promise(resolve => setTimeout(resolve, delay)); return retry(fn, retries - 1, delay * 2); // 指数退避 } }
七、总结对比表
八、最佳实践建议
- 优先使用 async/await 编写更清晰的代码
- 合理使用 Promise 方法(如 all/race)处理并行任务
- 不要忘记错误处理,使用 try/catch 或 .catch()
- 避免不必要的 await,能并行就不要顺序执行
- 注意 Promise 创建时机,避免意外提前执行
更多推荐
所有评论(0)