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

谢谢!


当前回答

的承诺。要么全部,要么一无所有。一旦数组中的所有承诺都被解决,它就会被解决,或者一旦其中一个承诺被拒绝,它就会被拒绝。换句话说,它要么使用所有已解析值的数组进行解析,要么使用单个错误进行拒绝。

一些图书馆有一种叫做承诺的东西。当,我理解它会等待数组中的所有承诺解决或拒绝,但我不熟悉它,它不在ES6中。

你的代码

我同意这里其他人的看法,您的修复应该有效。它应该使用一个包含成功值和错误对象的混合数组进行解析。在成功路径中传递错误对象是不寻常的,但假设您的代码期望它们,我认为这没有问题。

我能想到为什么它会“不解决”的唯一原因是它在代码中失败了,你没有向我们展示,而你没有看到任何关于此的错误消息的原因是因为这个承诺链没有以最终捕获终止(就你展示给我们的而言)。

我冒昧地从您的示例中提出了“现有链”,并用catch终止了该链。这可能不适合你,但对于阅读这篇文章的人来说,总是返回或终止链是很重要的,否则潜在的错误,甚至是编码错误,将被隐藏(这就是我怀疑在这里发生的事情):

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

其他回答

新回答

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的默认定义。

继续承诺。我写了一个名为executeAllPromises的实用函数。这个实用函数返回一个带有结果和错误的对象。

其思想是,传递给executeAllPromises的所有Promise都将被包装成一个新的Promise,该Promise将始终解决。新的Promise解析了一个有2个点的数组。第一个点保存解析值(如果有的话),第二个点保留错误(如果包装的Promise拒绝)。

作为最后一步,executeAllPromises会累积包装的promise的所有值,并返回带有结果数组和错误数组的最终对象。

代码如下:

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

在allsettle的帮助下,我们现在可以读取的状态 每个承诺都是,并单独处理每个错误,而不会丢失任何关键信息

const promises = [
    fetch('/api/first'), // first
    fetch('/api/second') // second
];

最简单的方法是处理错误

const [firstResult, secondResult] = await Promise.allSettled(promises)


 // Process first
 if (firstResult.status === 'rejected') {
   const err = firstResult.reason
   // Here you can handle error
 } else {
   const first = firstResult.value
 }

  // Process second
 if (secondResult.status === 'rejected') {
   const err = secondResult.reason
   // Here you can handle error
 } else {
   const second = secondResult.value
 }

处理错误的好方法

const results = await Promise.allSettled(promises);
const [first, second] = handleResults(results)


function handleResults(results) {
  const errors = results.filter(result => result.status === 'rejected').map(result => result.reason)

  if (errors.length) {
    // Aggregate all errors into one
    throw new AggregateError(errors)
  }

  return results.map(result => result.value)
}

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

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

如果您可以使用q库https://github.com/kriskowal/q 它有q. allsettle()方法可以解决这个问题 您可以根据每个承诺的状态来处理它,可以是完全提交的,也可以是拒绝的 所以

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