提问者:小点点

等到所有promise完成,即使有些promise被拒绝


假设我有一组正在发出网络请求的promise,其中一个将失败:

// http://does-not-exist will throw a TypeError
var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr)
  .then(res => console.log('success', res))
  .catch(err => console.log('error', err)) // This is executed   

假设我想等到所有这些都完成了,不管有没有一个失败了。可能有一个网络错误的资源,我可以生存没有,但如果我可以获得,我想要在我继续。我想优雅地处理网络故障。

由于promises.all没有为此留出任何空间,那么在不使用promissions库的情况下,处理此问题的推荐模式是什么?


共2个答案

匿名用户

更新时,您可能希望使用内置的本机promissione.allsettled:

Promise.allSettled([promise]).then(([result]) => {
   //reach here regardless
   // {status: "fulfilled", value: 33}
});

作为一个有趣事实,下面的回答是将方法添加到语言中的现有技术:]

当然,您只需要一个反射:

const reflect = p => p.then(v => ({v, status: "fulfilled" }),
                            e => ({e, status: "rejected" }));

reflect(promise).then((v => {
    console.log(v.status);
});

或使用ES5:

function reflect(promise){
    return promise.then(function(v){ return {v:v, status: "fulfilled" }},
                        function(e){ return {e:e, status: "rejected" }});
}


reflect(promise).then(function(v){
    console.log(v.status);
});

或者在您的示例中:

var arr = [ fetch('index.html'), fetch('http://does-not-exist') ]

Promise.all(arr.map(reflect)).then(function(results){
    var success = results.filter(x => x.status === "fulfilled");
});

匿名用户

类似的答案,但对于ES6来说可能更惯用:

null

const a = Promise.resolve(1);
const b = Promise.reject(new Error(2));
const c = Promise.resolve(3);

Promise.all([a, b, c].map(p => p.catch(e => e)))
  .then(results => console.log(results)) // 1,Error: 2,3
  .catch(e => console.log(e));


const console = { log: msg => div.innerHTML += msg + "<br>"};
<div id="div"></div>