javascript的Promise怎么用_如何优雅地处理异步操作?

Promise 是 JavaScript 处理异步的核心机制,具有 pending、fulfilled、rejected 三种不可逆状态;通过 new Promise 创建,用 .then() 处理成功、.catch() 统一捕获错误,支持链式调用与值透传,并行用 Promise.all() 或容错用 Promise.allSettled()。

Promise 是 JavaScript 中处理异步操作的核心机制,它让原本嵌套回调(callback hell)的代码变得线性、可读、易维护。用好 Promise 的关键不是记住语法,而是理解它的状态流转和链式逻辑。

Promise 的三种状态与基本创建

Promise 有 pending(进行中)、fulfilled(成功)、rejected(失败)三种状态,一旦改变就不可逆。创建 Promise 需传入一个执行器函数(executor),它接收 resolvereject 两个函数作为参数:

示例:封装一个延迟 1 秒后返回数据的异步操作

const fetchData = () => new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = Math.random() > 0.3;
    if (success) {
      resolve({ data: 'Hello World' });
    } else {
      reject(new Error('Network failed'));
    }
  }, 1000);
});

用 .then() 和 .catch() 处理结果

.then() 接收两个可选回调:第一个处理 fulfilled 状态,第二个处理 rejected(不推荐这样写);更推荐统一用 .catch() 捕获错误,因为:

  • .catch() 能捕获前面所有 .then() 中抛出的错误(包括同步异常)
  • 链式调用中错误会自动向下穿透,避免重复写错误处理
  • 语义更清晰:成功走 .then(),失败统一走 .catch()

正确写法:

fetchData()
  .then(res => console.log(res.data))
  .catch(err => console.error('出错了:', err.message));

链式调用与值的自动透传

每个 .then() 返回一个新的 Promise。如果返回的是普通值(如字符串、对象),会被自动包装成 resolved Promise;如果返回另一个 Promise,则等待它完成后再继续链式执行。这使得“串行异步”非常自然:

  • 第一步获取用户 ID → 第二步用 ID 请求用户详情 → 第三步渲染页面
  • 每一步都只关注自己的输入输出,不关心上一步怎么来的

示例:

getUserID()
  .then(id => fetchUserInfo(id)) // 返回 Promise
  .then(user => render(user))
  .catch(err => showError(err));

并行异步用 Promise.all(),容错用 Promise.allSettled()

多个独立请求需要同时发起时,别写多个 .then() 嵌套,用 Promise.all() 并发执行:

  • Promise.all([p1, p2, p3]):全部成功才 resolve,任一失败立即 reject
  • Promise.allSettled([p1, p2, p3]):不管成败都等全部结束,返回每个 Promise 的 {status, value/reason}
  • 需要“全量加载+部分失败也展示”时,优先选 allSettled

常见场景:同时拉取用户信息和最新通知

Promise.allSettled([
  fetchUser(),
  fetchNotifications()
]).then(results => {
  const [userRes, notifyRes] = results;
  if (userRes.status === 'fulfilled') showUser(userRes.value);
  if (notifyRes.status === 'fulfilled') showNotify(notifyRes.value);
});