Promise.all的使用、原理实现及错误处理


Promise.all 的使用、原理实现及错误处理

使用方式

Promise.all()方法将多个 Promise 实例包装成一个 Promise 对象(p),接受一个数组(p1,p2,p3)作为参数,数组中不一定需要都是 Promise 对象,但是一定具有 Iterator 接口,如果不是的话,就会调用 Promise.resolve 将其转化为 Promise 对象之后再进行处理。使用 Promise.all()生成的 Promise 对象(p)的状态是由数组中的 Promise 对象(p1,p2,p3)决定的;

  1. 如果所有的 Promise 对象(p1,p2,p3)都变成 fullfilled 状态的话,生成的 Promise 对象(p)也会变成 fullfilled 状态,p1,p2,p3 三个 Promise 对象产生的结果会组成一个数组返回给传递给 p 的回调函数;
  2. 如果 p1,p2,p3 中有一个 Promise 对象变为 rejected 状态的话,p 也会变成 rejected 状态,第一个被 rejected 的对象的返回值会传递给 p 的回调函数。
  3. Promise.all()方法生成的 Promise 对象也会有一个 catch 方法来捕获错误处理,但是如果数组中的 Promise 对象变成 rejected 状态时,并且这个对象还定义了 catch 的方法,那么 rejected 的对象会执行自己的 catch 方法,并且返回一个状态为 fullfilled 的 Promise 对象,Promise.all()生成的对象会接受这个 Promise 对象,不会返回 rejected 状态。
// 以下 demo,请求两个 url,当两个异步请求返还结果后,再请求第三个 url
const p1 = request(`http://some.url.1`);
const p2 = request(`http://some.url.2`);
Promise.all([p1, p2])
  .then((datas) => {
    // 此处 datas 为调用 p1, p2 后的结果的数组
    return request(`http://some.url.3?a=${datas[0]}&b=${datas[1]}`);
  })
  .then((data) => {
    console.log(msg);
  });

实现

function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    if (!Array.isArray(promises)) {
      return reject(new TypeError("argument must be an array"));
    }
    let countNum = 0;
    let promiseNum = promises.length;
    let resolvedvalue = new Array(promiseNum);
    // for (var i = 0; i < promiseNum; i++) {
    //   (function (i) {
    //     Promise.resolve(promises[i]).then(
    //       function (value) {
    //         countNum++;
    //         resolvedvalue[i] = value;
    //         if (countNum === promiseNum) {
    //           return resolve(resolvedvalue);
    //         }
    //       },
    //       function (reason) {
    //         return reject(reason);
    //       }
    //     );
    //   })(i);
    // }
    promises.map((promise, i) => {
      Promise.resolve(promise).then(
        (val) => {
          countNum++;
          resolvedvalue[i] = val;
          if (countNum === promiseNum) {
            resolve(resolvedvalue);
          }
        },
        (err) => {
          reject(err);
        }
      );
    });
  });
}
let p1 = Promise.resolve(1),
  p2 = Promise.resolve(2),
  p3 = Promise.resolve(3);
promiseAll([p1, p2, p3]).then(function (value) {
  console.log(value); //  [ 1, 2, 3 ]
});

错误处理

在有一个 promise 出错的情况下 promise.all 仍然能返回其他正确数据

var p1 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve(1);
  }, 0);
});
var p2 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve(2);
  }, 200);
});
var p3 = new Promise(function (resolve, reject) {
  setTimeout(function () {
    try {
      console.log(XX.BBB);
    } catch (exp) {
      resolve("error");
    }
  }, 100);
});
Promise.all([p1, p2, p3])
  .then(function (results) {
    console.log("success");
    console.log(results);
  })
  .catch(function (r) {
    console.log("err");
    console.log(r);
  });
//success
//[ 1, 2, 'error' ]

参考

每日两题 T12


文章作者: CassielLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 CassielLee !
评论
  目录