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

谢谢!


当前回答

ES2020为Promise类型引入了新的方法:Promise. allsettle()。

的承诺。当所有输入承诺都已解决时,allsettle会给你一个信号,这意味着它们要么被满足,要么被拒绝。这在不关心承诺状态的情况下很有用,您只想知道工作何时完成,而不管它是否成功。

异步函数(){ Const promises = [ Fetch ('/api.stackexchange.com/2.2'), //成功 Fetch ('/this-will-fail') //失败 ]; const result = await promise . allsettle (promises); console.log(结果。Map (promise => promise.status)); // [' completed ', 'rejected'] }

详见v8博客文章。

其他回答

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

使用Async await -

这里一个异步函数func1返回一个解析值,func2抛出一个错误并返回null,在这种情况下,我们可以按照自己的想法处理它并相应地返回。

const callingFunction  = async () => {
    const manyPromises = await Promise.all([func1(), func2()]);
    console.log(manyPromises);
}


const func1 = async () => {
    return 'func1'
}

const func2 = async () => {
    try {
        let x;
        if (!x) throw "x value not present"
    } catch(err) {
       return null
    }
}

callingFunction();

输出是- ['func1', null]

继续承诺。我写了一个名为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}`); });

不幸的是,我没有足够的声誉来评论(或者做任何事情,真的),所以我把这篇文章作为对Eric的回答的回应。

executor函数也可以是异步函数。然而,这通常是一个错误,原因如下: 如果异步执行器函数抛出错误,错误将被丢失,不会导致新构造的Promise被拒绝。这可能会使调试和处理某些错误变得困难。 如果Promise执行函数使用await,这通常表明实际上不需要使用新的Promise构造函数,或者可以缩小新的Promise构造函数的作用域。

由此解释了为什么promise不应该使用异步执行器函数

相反,您应该选择promise . allsettle(),就像Asaf在这里建议的那样。

这就是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);
        });
    });
}