我有一个promise数组,我用Promise.all(arrayOfPromises)来解析它;

我继续承诺链。大概是这样的

existingPromiseChain = existingPromiseChain.then(function() {
  var arrayOfPromises = state.routes.map(function(route){
    return route.handler.promiseHandler();
  });
  return Promise.all(arrayOfPromises)
});

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
  // do stuff with my array of resolved promises, eventually ending with a res.send();
});

我想添加一个catch语句来处理一个单独的promise,以防它出错,但是当我尝试时,promise。all返回它找到的第一个错误(忽略其余的错误),然后我就不能从数组中的其余承诺(没有错误)中获得数据。

我试过做一些像…

existingPromiseChain = existingPromiseChain.then(function() {
      var arrayOfPromises = state.routes.map(function(route){
        return route.handler.promiseHandler()
          .then(function(data) {
             return data;
          })
          .catch(function(err) {
             return err
          });
      });
      return Promise.all(arrayOfPromises)
    });

existingPromiseChain = existingPromiseChain.then(function(arrayResolved) {
      // do stuff with my array of resolved promises, eventually ending with a res.send();
});

但这并不能解决问题。

谢谢!

--

编辑:

下面的答案是完全正确的,代码被破坏是由于其他原因。如果有人感兴趣,这是我最终得出的解决方案……

节点快速服务器链

serverSidePromiseChain
    .then(function(AppRouter) {
        var arrayOfPromises = state.routes.map(function(route) {
            return route.async();
        });
        Promise.all(arrayOfPromises)
            .catch(function(err) {
                // log that I have an error, return the entire array;
                console.log('A promise failed to resolve', err);
                return arrayOfPromises;
            })
            .then(function(arrayOfPromises) {
                // full array of resolved promises;
            })
    };

API调用(路由。异步调用)

return async()
    .then(function(result) {
        // dispatch a success
        return result;
    })
    .catch(function(err) {
        // dispatch a failure and throw error
        throw err;
    });

把。catch作为承诺。在.then之前的所有内容似乎都用于从原始的promise中捕获任何错误,但随后将整个数组返回到下一个.then

谢谢!


当前回答

Promise.allSettled

而不是承诺。都使用Promise。等待所有承诺的解决,不管结果如何

let p1 = new Promise(resolve => resolve("result1")); let p2 = new Promise((resolve,reject) => reject('some trouble ')); let p3 = new Promise(resolve => resolve("result3")); //返回每个promise状态和值的信息 Promise.allSettled ((p1, p2, p3))。然后(结果= > console.log(结果));

Polyfill

if (! promise . allsettle) { const rejectHandler = reason => ({status: 'rejected', reason}); const resolveHandler = value =>({状态:'已完成',value}); 的承诺。allsettle =函数(承诺){ const convertedPromises = promises .map(p =>承诺。resolve(p)。然后(resolveHandler rejectHandler)); 返回Promise.all (convertedPromises); }; }

其他回答

或者,如果你有这样的情况,当有一个失败时,你并不特别关心已解决的承诺的值,但你仍然希望它们运行,你可以这样做,当它们都成功时,你会正常地解决承诺,当它们中的任何一个失败时,你会拒绝失败的承诺:

function promiseNoReallyAll (promises) {
  return new Promise(
    async (resolve, reject) => {
      const failedPromises = []

      const successfulPromises = await Promise.all(
        promises.map(
          promise => promise.catch(error => {
            failedPromises.push(error)
          })
        )
      )

      if (failedPromises.length) {
        reject(failedPromises)
      } else {
        resolve(successfulPromises)
      }
    }
  )
}

Promise.allSettled

而不是承诺。都使用Promise。等待所有承诺的解决,不管结果如何

let p1 = new Promise(resolve => resolve("result1")); let p2 = new Promise((resolve,reject) => reject('some trouble ')); let p3 = new Promise(resolve => resolve("result3")); //返回每个promise状态和值的信息 Promise.allSettled ((p1, p2, p3))。然后(结果= > console.log(结果));

Polyfill

if (! promise . allsettle) { const rejectHandler = reason => ({status: 'rejected', reason}); const resolveHandler = value =>({状态:'已完成',value}); 的承诺。allsettle =函数(承诺){ const convertedPromises = promises .map(p =>承诺。resolve(p)。然后(resolveHandler rejectHandler)); 返回Promise.all (convertedPromises); }; }

你考虑过Promise.prototype.finally()吗?

它的设计似乎完全是为了做你想做的事情——一旦所有的承诺都解决了(解决/拒绝),就执行一个函数,而不管其中一些承诺是否被拒绝。

来自MDN文档:

如果您希望在承诺确定之后进行一些处理或清理,而不管其结果如何,那么finally()方法可能很有用。

finally()方法非常类似于调用.then(onFinally, onFinally),但是有一些区别:

在内联创建函数时,可以传递一次,而不是被迫声明两次,或者为它创建一个变量。

finally回调将不会接收任何参数,因为没有可靠的方法来确定承诺是否被实现或拒绝。当您不关心被拒绝的原因或实现价值时,这个用例恰好适用,因此不需要提供它。

与Promise.resolve(2).then(() =>{},() =>{})(将被未定义解析)不同,Promise.resolve(2).finally(() =>{})将被2解析。 类似地,与Promise.reject(3).then(() =>{},() =>{})(将用undefined实现)不同,Promise.reject(3).finally(() =>{})将被3拒绝。

==后退==

如果你的JavaScript版本不支持Promise.prototype.finally(),你可以使用Jake Archibald的这个变通方法:Map (p => p.catch(() => undefined)));

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
let sum = 0;
let promiseErrorArr = [];

Promise.allSettled(promises)
.then((results) => {
          results.forEach(result => {
            if (result.status === "rejected") {
              sum += 1;
              promiseErrorArr.push(result)
            }
          })
    return ( (sum>0) ? promiseFailed() : promisePassed())
})

function promiseFailed(){
  console.log('one or all failed!')
  console.log(promiseErrorArr)
}

function promisePassed(){
  console.log('all passed!')
}

// expected output:
// "one or all failed!"
// Array [Object { status: "rejected", reason: "foo" }]

我写了一个npm库来处理这个问题更漂亮。 https://github.com/wenshin/promiseallend

安装

npm i --save promiseallend

2017-02-25新增api,不违背承诺原则

const promiseAllEnd = require('promiseallend');

const promises = [Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)];
const promisesObj = {k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)};

// input promises with array
promiseAllEnd(promises, {
    unhandledRejection(error, index) {
        // error is the original error which is 'error'.
        // index is the index of array, it's a number.
        console.log(error, index);
    }
})
    // will call, data is `[1, undefined, 2]`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// input promises with object
promiseAllEnd(promisesObj, {
    unhandledRejection(error, prop) {
        // error is the original error.
        // key is the property of object.
        console.log(error, prop);
    }
})
    // will call, data is `{k1: 1, k3: 2}`
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

// the same to `Promise.all`
promiseAllEnd(promises, {requireConfig: true})
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [false, true, false]})
    // won't call
    .then(data => console.log(data))
    // will call, `error.detail` is 'error', `error.key` is number 1.
    .catch(error => console.log(error.detail))

// requireConfig is Array
promiseAllEnd(promises, {requireConfig: [true, false, false]})
    // will call, data is `[1, undefined, 2]`.
    .then(data => console.log(data))
    // won't call
    .catch(error => console.log(error.detail))

————————————————————————————————

旧的坏api,不要使用它!

let promiseAllEnd = require('promiseallend');

// input promises with array
promiseAllEnd([Promise.resolve(1), Promise.reject('error'), Promise.resolve(2)])
    .then(data => console.log(data)) // [1, undefined, 2]
    .catch(error => console.log(error.errorsByKey)) // {1: 'error'}

// input promises with object
promiseAllEnd({k1: Promise.resolve(1), k2: Promise.reject('error'), k3: Promise.resolve(2)})
    .then(data => console.log(data)) // {k1: 1, k3: 2}
    .catch(error => console.log(error.errorsByKey)) // {k2: 'error'}