Promise.all

228 阅读2分钟

简述

  • Promise.all 用于并行执行多个 Promise;
  • 接收一个promise实例的iterable(数组)作为参数,并返回一个新的Promise实例;
  • 返回的新的Promise实例会在给定的Promise都成功解决后才会被解决,其结果是由每个Promise结果组成的数组
  • 如果一个Promise被拒绝,整个Promise.all会被立即拒绝,不会再等待其他Promise完成

手写

function myPromiseAll(iterable) {
    return new Promise((resolve,reject) => {
        const promises = Array.from(iterable);
        // 定义Promise对象resolve的数组
        const result = [];
        // 定义一个计数器用来判断是否所有的promise执行完毕
        let count = 0;
        // 并发执行每一个promise
        for (let i = 0; i < promises.length; i++) {
            // 确保每项都可被当作一个Promise来处理,即使传入非Promise值
            Promise.resolve(promises[i]).then(res => {
                result[i] = res;
                count++;
                if (count === promises.length) {
                    resolve(result);
                }
            }).catch(err => reject(err))
        }
    })
}

注意:

  • 并不是push进result数组的,而是通过下标的方式进行存储,这是因为我们为了保证输出的顺序,因为Promise对象执行的时间可能不同,push的话会破坏顺序。
  • 通过计数标志来判断是否所有的promise对象都执行完毕了,因为在then中表示该promise对象已经执行完毕。

注意问题

1 入参是串行 or 并行执行 —— 并行

验证代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 手写promise all
      function myPromiseAll(iterable) {
        return new Promise((resolve, reject) => {
          const promises = Array.from(iterable);
          // 定义Promise对象resolve的数组
          const result = [];
          // 定义一个计数器用来判断是否所有的promise执行完毕
          let count = 0;
          // 并发执行每一个promise
          for (let i = 0; i < promises.length; i++) {
            Promise.resolve(promises[i])
              .then((res) => {
                result[i] = res;
                count++;
                if (count === promises.length) {
                  resolve(result);
                }
              })
              .catch((err) => reject(err));
          }
        });
      }
      const p1 = new Promise(async (resolve) => {
        console.log('p1开始');
        await new Promise((resolve) => setTimeout(resolve, 1000));
        console.log('p1结束');
      });
      const p2 = new Promise(async (resolve, reject) => {
        console.log('p2开始');
        await new Promise((resolve) => setTimeout(resolve, 3000));
        console.log('p2结束');
      });
      myPromiseAll([p1, p2])
        .then((res) => {
          console.log(333, res);
        })
        .catch((err) => {
          console.log(err);
        });
    </script>
  </body>
</html>