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

其他回答

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

您需要知道如何识别结果中的错误。如果您没有标准的预期错误,我建议您对catch块中的每个错误运行转换,使其在结果中可识别。

try {
  let resArray = await Promise.all(
    state.routes.map(route => route.handler.promiseHandler().catch(e => e))
  );

  // in catch(e => e) you can transform your error to a type or object
  // that makes it easier for you to identify whats an error in resArray
  // e.g. if you expect your err objects to have e.type, you can filter
  // all errors in the array eg
  // let errResponse = resArray.filter(d => d && d.type === '<expected type>')
  // let notNullResponse = resArray.filter(d => d)

  } catch (err) {
    // code related errors
  }

新回答

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

如果您可以使用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();
});

这不是记录错误日志的最佳方法,但是您总是可以为promiseAll设置一个数组,并将结果存储到新变量中。

如果你使用graphQL,你需要后处理响应,无论如何,如果它没有找到正确的引用,它将崩溃应用程序,缩小问题所在

const results = await Promise.all([
  this.props.client.query({
    query: GET_SPECIAL_DATES,
  }),
  this.props.client.query({
    query: GET_SPECIAL_DATE_TYPES,
  }),
  this.props.client.query({
    query: GET_ORDER_DATES,
  }),
]).catch(e=>console.log(e,"error"));
const specialDates = results[0].data.specialDates;
const specialDateTypes = results[1].data.specialDateTypes;
const orderDates = results[2].data.orders;