处理Promise.all中的错误

我有一组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.all返回它find的第一个错误(忽略其余部分),然后我无法从其余的数组中的承诺(即没有错误)。

我试过做一些像..

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

但是这并没有解决。

谢谢!

编辑:

下面的答案完全正确,代码由于其他原因而中断。 如果有人有兴趣,这是我最终的解决scheme…

节点快递服务器链

 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调用(route.async调用)

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

将.catch放在Promise.all之前,似乎已经达到了从原来的承诺中捕获任何错误的目的,然后将整个数组返回到下一个。

谢谢!

Promise.all全部或全部。 一旦数组中的所有承诺解决,它就会解决,或者一旦拒绝,就立即拒绝。 换句话说,它要么解决所有parsing值的数组,要么拒绝一个单一的错误。

有些库有一些叫做Promise.when东西。 Promise.when我知道它会等待数组中的所有承诺来解决或拒绝,但是我不熟悉它,它不在ES6中。

你的代码

我同意这里的其他人,你的修复应该工作。 它应该用一个可能包含成功的值和错误对象的数组来解决。 在成功path中传递错误对象是不正常的,但假设你的代码正在期待它们,我没有看到它的问题。

我能想到为什么它“不能解决”的唯一原因是它没有向你展示我们的代码,你没有看到任何关于这个错误的原因是因为这个promise链没有终止赶上(至于你反正给我们看)。

我冒昧地从你的榜样中分解出“现有的链条”,并以一个抓住的方式终止链条。 这可能不适合你,但是对于阅读这些内容的人来说,重要的是始终要么返回或终止链,要么潜在的错误,甚至是编码错误,都会被隐藏起来(这是我怀疑发生的事情):

 Promise.all(state.routes.map(function(route) { return route.handler.promiseHandler().catch(function(err) { return err; }); })) .then(function(arrayOfValuesOrErrors) { // handling of my array containing values and/or errors. }) .catch(function(err) { console.log(err.message); // some coding error in handling happened }); 

如果你使用q库https://github.com/kriskowal/q它有q.allSettled()方法可以解决这个问题,你可以处理每个承诺根据其状态全文或拒绝所以;

 existingPromiseChain = existingPromiseChain.then(function() { var arrayOfPromises = state.routes.map(function(route){ return route.handler.promiseHandler(); }); return q.allSettled(arrayOfPromises) }); existingPromiseChain = existingPromiseChain.then(function(arrayResolved) { //so here you have all your promises the fulfilled and the rejected ones // you can check the state of each promise arrayResolved.forEach(function(item){ if(item.state === 'fulfilled'){ // 'rejected' for rejected promises //do somthing } else { // do something else } }) // do stuff with my array of resolved promises, eventually ending with a res.send(); }); 

要继续Promise.all循环(即使Promise拒绝),我写了一个名为executeAllPromises的实用程序函数。 此实用程序函数返回一个包含resultserrors的对象。

这个想法是,你传递给executeAllPromises所有Promise将被包装成一个新的Promise,这个Promise将会一直解决。 新的Promise解决了有2个点的数组。 第一个点保存parsing值(如果有),第二个点保存错误(如果包装的Promise拒绝)。

作为最后一步, executeAllPromises累积包装的promise的所有值,并返回最后一个对象,其中包含results数组和errors数组。

这里是代码:

 function executeAllPromises(promises) { // Wrap all Promises in a Promise that will always "resolve" var resolvingPromises = promises.map(function(promise) { return new Promise(function(resolve) { var payload = new Array(2); promise.then(function(result) { payload[0] = result; }) .catch(function(error) { payload[1] = error; }) .then(function() { /* * The wrapped Promise returns an array: * The first position in the array holds the result (if any) * The second position in the array holds the error (if any) */ resolve(payload); }); }); }); var errors = []; var results = []; // Execute all wrapped Promises return Promise.all(resolvingPromises) .then(function(items) { items.forEach(function(payload) { if (payload[1]) { errors.push(payload[1]); } else { results.push(payload[0]); } }); return { errors: errors, results: results }; }); } var myPromises = [ Promise.resolve(1), Promise.resolve(2), Promise.reject(new Error('3')), Promise.resolve(4), Promise.reject(new Error('5')) ]; executeAllPromises(myPromises).then(function(items) { // Result var errors = items.errors.map(function(error) { return error.message }).join(','); var results = items.results.join(','); console.log(`Executed all ${myPromises.length} Promises:`); console.log(`— ${items.results.length} Promises were successful: ${results}`); console.log(`— ${items.errors.length} Promises failed: ${errors}`); }); 

我们必须编写自定义的Promise.all()。 这里我在我的项目中使用的解决scheme。 正常结果将返回错误。 毕竟承诺完成后,我们可以滤除错误。

 const Promise_all = promises => { return new Promise((resolve, reject) => { const results = []; let count = 0; promises.forEach((promise, idx) => { promise .catch(err => { return err; }) .then(valueOrError => { results[idx] = valueOrError; count += 1; if (count === promises.length) resolve(results); }); }); }); }; const results = await Promise_all(promises) const validResults = results.filter(result => !(result instanceof Error)); 

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