Resolve *and* reject all promises in Bluebird

2019-05-23 03:37发布

问题:

I'm looking for the way to get both resolutions and rejections from promise array. I'm currently counting on Bluebird implementation, so ES6 compatible solution would be suitable, too.

The best thing that comes to mind is to use Bluebird's Promise.settle for that, and I consider promise inspections an unnecessary complication here:

  let promises = [
    Promise.resolve('resolved'),
    Promise.resolve('resolved'),
    Promise.reject('rejected')
  ];

  // is there an existing way to do this?
  let resolvedAndRejected = Promise.settle(promises)
  .then((inspections) => {
    let resolved = [];
    let rejected = [];

    inspections.forEach((inspection) => {
      if (inspection.isFulfilled())
        resolved.push(inspection.value());
      else if (inspection.isRejected())
        rejected.push(inspection.reason());
    });

    return [resolved, rejected];
  });

  resolvedAndRejected.spread((resolved, rejected) => {
    console.log(...resolved);
    console.error(...rejected);
  });

It looks like a trivial task for the cases where 100% fulfillment rate isn't an option or a goal, but I don't even know the name for the recipe.

Is there a neat and well-proven way to handle this in Bluebird or other promise implementations - built-in operator or extension?

回答1:

Added answer for completeness since OP asked. Here is what I'd do:

 const res = Promise.all(promises.map(p => p.reflect())) // get promises
   .then(values => [
          values.filter(x => x.isFulfilled()).map(x => x.value()), // resolved
          values.filter(x => x.isRejected()).map(x => x.reason()) // rejected
   ]);


回答2:

There's nothing built in for it, but reduce can make it pretty succinct:

Promise
  .settle(promises)
  .reduce(([resolved, rejected], inspection) => {
    if (inspection.isFulfilled())
      resolved.push(inspection.value());
    else
      rejected.push(inspection.reason());
    return [resolved, rejected];
  }, [[], []]);


回答3:

You can use Promise.all(), handle rejected Promise, return reason or other value to chained .then()

let promises = [
  Promise.resolve("resolved"),
  Promise.resolve("resolved"),
  Promise.reject("rejected")
]
, results = {resolved:[], rejected:[]}

, resolvedAndRejected = Promise.all(
  promises.map((p) => {
    return p.then((resolvedValue) => {
      results.resolved.push(resolvedValue);
      return resolvedValue
    }, (rejectedReason) => {
      results.rejected.push(rejectedReason);
      return rejectedReason
    })
  }));

resolvedAndRejected.then((data) => {
  console.log(data, results)
});