我有一个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

谢谢!


当前回答

我写了一个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'}

其他回答

这就是Promise。一切都是为了工作而设计。如果只有一个promise reject(),整个方法立即失败。

有一些用例可能需要Promise。都是为了让承诺落空。要做到这一点,只需不要在承诺中使用任何reject()语句。然而,为了确保你的应用程序/脚本不会在任何一个底层承诺从未得到响应的情况下冻结,你需要给它设置一个超时。

function getThing(uid,branch){
    return new Promise(function (resolve, reject) {
        xhr.get().then(function(res) {
            if (res) {
                resolve(res);
            } 
            else {
                resolve(null);
            }
            setTimeout(function(){reject('timeout')},10000)
        }).catch(function(error) {
            resolve(null);
        });
    });
}

新回答

const results = await Promise.all(promises.map(p => p.catch(e => e)));
const validResults = results.filter(result => !(result instanceof Error));

未来承诺API

Chrome 76: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled 现在就可以下载https://www.npmjs.com/package/promise.allsettled获取。在某些浏览器中,allsettle是与浏览器一起预安装的。为了心安,下载这个软件包是值得的。TypeScript没有allsettle的默认定义。

对于那些使用ES8的人来说,你可以使用异步函数做如下的事情:

var arrayOfPromises = state.routes.map(async function(route){
  try {
    return await route.handler.promiseHandler();
  } catch(e) {
    // Do something to handle the error.
    // Errored promises will return whatever you return here (undefined if you don't return anything).
  }
});

var resolvedPromises = await Promise.all(arrayOfPromises);

正如@jib所说,

的承诺。要么全部,要么一无所有。

不过,您可以控制某些“允许”失败的承诺,我们希望继续进行。

为例。

  Promise.all([
    doMustAsyncTask1,
    doMustAsyncTask2,
    doOptionalAsyncTask
    .catch(err => {
      if( /* err non-critical */) {
        return
      }
      // if critical then fail
      throw err
    })
  ])
  .then(([ mustRes1, mustRes2, optionalRes ]) => {
    // proceed to work with results
  })

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); }; }