JavaScript 教程:深入理解 Promise API

JavaScript 教程:深入理解 Promise API

【免费下载链接】ru.javascript.info Современный учебник JavaScript 【免费下载链接】ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

Promise 是 JavaScript 异步编程的核心概念之一,它提供了比传统回调函数更优雅的异步处理方式。本文将全面解析 Promise 类提供的 6 个静态方法,帮助你掌握 Promise 的高级用法。

为什么需要 Promise API

在复杂的异步编程场景中,我们经常需要处理多个异步操作的组合、竞争或依赖关系。Promise API 提供了一系列静态方法来简化这些常见模式的处理。

1. Promise.all:并行执行多个 Promise

Promise.all 是最常用的方法之一,它允许我们并行执行多个 Promise,并等待所有 Promise 都完成。

基本用法

let promise = Promise.all([promise1, promise2, ...]);

特点:

  • 接收一个可迭代对象(通常是数组)
  • 返回一个新的 Promise
  • 当所有 Promise 都成功时,返回结果数组
  • 顺序与输入顺序一致,不受完成时间影响
  • 任何一个 Promise 失败,立即拒绝

实际应用示例

// 同时获取多个用户信息
let userIds = [1, 2, 3];
let userPromises = userIds.map(id => fetch(`/users/${id}`));

Promise.all(userPromises)
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(users => {
    // 处理所有用户数据
  })
  .catch(error => {
    // 处理任一请求失败的情况
  });

注意事项

  • 一旦某个 Promise 失败,其他 Promise 的结果会被忽略
  • 可以传递非 Promise 值,它们会被直接包含在结果数组中
  • 适用于"全部成功或全部失败"的场景

2. Promise.allSettled:获取所有 Promise 的最终状态

Promise.allSettled 是较新的 API,它会等待所有 Promise 完成(无论成功或失败)。

与 Promise.all 的区别

  • 不会因为某个 Promise 失败而立即拒绝
  • 总是返回一个包含所有 Promise 结果的对象数组
  • 每个结果对象包含 status 属性("fulfilled"或"rejected")

使用场景

// 获取多个资源,即使部分失败也要继续处理
Promise.allSettled([
  fetch('/data'),
  fetch('/config'),
  fetch('/user')
]).then(results => {
  results.forEach(result => {
    if(result.status === 'fulfilled') {
      console.log('成功:', result.value);
    } else {
      console.log('失败:', result.reason);
    }
  });
});

兼容性处理

对于不支持的环境,可以使用 polyfill:

if(!Promise.allSettled) {
  Promise.allSettled = function(promises) {
    return Promise.all(promises.map(p => 
      Promise.resolve(p).then(
        value => ({ status: 'fulfilled', value }),
        error => ({ status: 'rejected', reason: error })
      )
    );
  };
}

3. Promise.race:竞速模式

Promise.race 返回第一个完成的 Promise(无论成功或失败)。

典型用法

// 设置超时机制
function fetchWithTimeout(url, timeout) {
  return Promise.race([
    fetch(url),
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('请求超时')), timeout)
    )
  ]);
}

注意事项

  • 只关心第一个完成的 Promise
  • 其他 Promise 的结果会被忽略
  • 适用于超时处理或竞速场景

4. Promise.any:首个成功的 Promise

Promise.any 是较新的 API,它等待第一个成功的 Promise。

特点

  • 忽略所有失败的 Promise,直到第一个成功的出现
  • 如果所有 Promise 都失败,返回 AggregateError
  • 适用于"任一成功即可"的场景

示例

// 尝试多个镜像服务器
Promise.any([
  fetch('https://mirror1.com/data'),
  fetch('https://mirror2.com/data'),
  fetch('https://mirror3.com/data')
]).then(data => {
  // 使用第一个成功的响应
}).catch(error => {
  // 所有请求都失败了
  console.log(error.errors); // 查看所有错误
});

5. Promise.resolve 和 Promise.reject

这两个方法用于创建已确定状态的 Promise。

Promise.resolve

// 创建一个已解决的 Promise
let cachedPromise = Promise.resolve(cachedData);

// 等同于
let cachedPromise = new Promise(resolve => resolve(cachedData));

使用场景:

  • 确保函数总是返回 Promise
  • 缓存已获取的数据
  • 包装同步值为 Promise

Promise.reject

// 创建一个已拒绝的 Promise
let errorPromise = Promise.reject(new Error('失败'));

// 等同于
let errorPromise = new Promise((_, reject) => reject(new Error('失败')));

在现代代码中,这两个方法使用频率较低,因为有 async/await 语法糖。

总结对比表

方法描述成功条件失败条件
Promise.all所有 Promise 成功返回结果数组任一失败立即拒绝
Promise.allSettled所有 Promise 完成返回状态对象数组不会拒绝
Promise.race第一个完成的 Promise可能成功或失败可能成功或失败
Promise.any第一个成功的 Promise返回第一个成功结果所有都失败才拒绝
Promise.resolve创建已解决的 Promise总是成功-
Promise.reject创建已拒绝的 Promise-总是失败

最佳实践建议

  1. 并行请求使用 Promise.all,但要考虑错误处理
  2. 需要完整结果时使用 Promise.allSettled
  3. 超时控制使用 Promise.race
  4. 备用方案优先使用 Promise.any
  5. 避免过度使用 Promise.resolve/reject,优先使用 async/await

掌握这些 Promise API 的组合使用,可以让你在复杂异步场景下游刃有余,写出更健壮、更易维护的 JavaScript 代码。

【免费下载链接】ru.javascript.info Современный учебник JavaScript 【免费下载链接】ru.javascript.info 项目地址: https://gitcode.com/gh_mirrors/ru/ru.javascript.info

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值