Promise 是 JavaScript 中处理异步操作的重要机制,它代表一个异步操作的最终完成或失败。Promise 有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态改变,就不会再变。
核心概念
Promise 的三种状态
- pending: 初始状态,既不是成功也不是失败
- fulfilled: 操作成功完成
- rejected: 操作失败
基本用法
javascriptconst promise = new Promise((resolve, reject) => { // 异步操作 setTimeout(() => { if (/* 操作成功 */) { resolve('成功的结果'); } else { reject('失败的原因'); } }, 1000); }); promise.then(result => { console.log(result); // 处理成功 }).catch(error => { console.log(error); // 处理失败 });
Promise 链式调用
javascriptfetch('/api/user') .then(response => response.json()) .then(user => fetch(`/api/posts/${user.id}`)) .then(response => response.json()) .then(posts => console.log(posts)) .catch(error => console.error(error));
Promise 静态方法
Promise.all(): 所有 Promise 都成功才返回成功,有一个失败就返回失败
javascriptPromise.all([promise1, promise2, promise3]) .then(results => console.log(results)) .catch(error => console.error(error));
Promise.race(): 返回最先完成的结果(无论成功或失败)
javascriptPromise.race([promise1, promise2]) .then(result => console.log(result));
Promise.allSettled(): 等待所有 Promise 完成,返回每个 Promise 的状态
javascriptPromise.allSettled([promise1, promise2]) .then(results => console.log(results));
Promise.any(): 返回第一个成功的 Promise
javascriptPromise.any([promise1, promise2]) .then(result => console.log(result));
常见面试问题
1. Promise 和回调函数的区别
- Promise 解决了回调地狱问题
- Promise 提供了更好的错误处理机制
- Promise 支持链式调用,代码更清晰
- Promise 状态不可逆,更符合直觉
2. 如何处理 Promise 错误
使用 .catch() 方法捕获错误,或者在 .then() 的第二个参数中处理:
javascriptpromise.then( result => console.log(result), error => console.error(error) ); // 或者 promise.then(result => console.log(result)) .catch(error => console.error(error));
3. Promise 的微任务机制
Promise 的回调属于微任务,会在当前宏任务执行完后立即执行,优先级高于宏任务(如 setTimeout)。
4. async/await 与 Promise 的关系
async/await 是 Promise 的语法糖,让异步代码看起来像同步代码:
javascriptasync function fetchData() { try { const response = await fetch('/api/data'); const data = await response.json(); return data; } catch (error) { console.error(error); } }
最佳实践
- 总是处理错误: 使用
.catch()或 try/catch - 避免嵌套 Promise: 使用链式调用
- 合理使用 Promise 静态方法: 根据场景选择合适的方法
- 理解事件循环: 掌握微任务和宏任务的执行顺序
- 性能优化: 避免不必要的 Promise 包装