Promise.all的理解以及手写Promise.all

在现代JavaScript开发中,异步编程已经成为必不可少的一部分。为了处理异步操作,JavaScript 提供了多种工具和方法,其中最重要的一种就是 Promise。并且 Promise 中的 Promise.all ,这是一个强大的工具,可以帮助开发者有效地管理多个并发异步操作。

什么是 Promise.all?

Promise.all 是 JavaScript 中的一个静态方法,它接收一个可迭代对象(如数组)作为参数,这个参数包含多个 Promise 实例。Promise.all 返回一个新的 Promise,该 Promise 只有在所有传入的 Promise 都已解决或其中一个 Promise 被拒绝时才会结束。

语法

Promise.all(iterable);
  • iterable 是一个可迭代对象,包含多个 Promise 或其他值(这些值会被隐式地转换成 resolved 状态的 Promise)。

返回值是一个新的 Promise 实例。

使用示例

让我们通过一个简单的例子来理解 Promise.all 的工作原理。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values); // [3, 42, "foo"]
});

在上面的示例中,Promise.all 接收一个包含三个 Promise 的数组。它返回一个新的 Promise,当这三个 Promise 都被解决时,它会被解决,并且其值是一个包含这三个 Promise 的解决值的数组。

错误处理

如果传入的 Promise 中有一个被拒绝,Promise.all 返回的 Promise 也会被拒绝,并且拒绝的原因是第一个被拒绝的 Promise 的原因。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, 'error occurred');
});
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 200, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
}).catch((error) => {
  console.log(error); // "error occurred"
});

在这个示例中,第二个 Promise 被拒绝,因此 Promise.all 返回的 Promise 也会立即被拒绝,且拒绝的原因是第二个 Promise 的拒绝原因。

实际应用场景

1. 并行执行多个异步操作

Promise.all 可以用来并行执行多个异步操作,并且只有在所有操作都完成后才继续执行后续代码。这在需要同时获取多个数据源的数据时特别有用。

const fetchData1 = fetch('/api/data1');
const fetchData2 = fetch('/api/data2');
const fetchData3 = fetch('/api/data3');

Promise.all([fetchData1, fetchData2, fetchData3])
  .then(responses => {
    return Promise.all(responses.map(response => response.json()));
  })
  .then(data => {
    console.log(data); // [data1, data2, data3]
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });

2. 处理多个独立的异步操作

在某些情况下,我们可能需要执行多个彼此独立的异步操作,并在它们全部完成后进行处理。Promise.all 可以很好地解决这个问题。

const processImage = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'Image processed');
});

const uploadImage = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'Image uploaded');
});

const generateThumbnail = new Promise((resolve, reject) => {
  setTimeout(resolve, 1500, 'Thumbnail generated');
});

Promise.all([processImage, uploadImage, generateThumbnail])
  .then(results => {
    console.log(results); // ["Image processed", "Image uploaded", "Thumbnail generated"]
  })
  .catch(error => {
    console.error('Error:', error);
  });

手写Promise.all

function myPromiseAll(promises) {
  if (!Array.isArray(promises)) {
    return Promise.reject(new Error('promises must be an array'))
  }
  let cnt = 0, res = []
  return new Promise((resolve, reject) => {
    promises.forEach((promise) => {
      // 使用 Promise.resolve 包装它,以确保即使传入的是非 Promise 值(如普通值),它也会被转换成一个已经解决的 Promise。
      Promise.resolve(promise).then((result) => {
        // 如果成功,将结果存入 res 数组,并增加计数器  
        cnt++
        res.push(result)
        // 如果所有 promise 都已解决,则调用 resolve
        if (cnt === promises.length) {
          resolve(res)
        }
      },
      // 如果失败,则立即调用 reject   
      (error) => {
        reject(error)
      })
    });
  })
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值