Подтвердить что ты не робот

Bluebird Promise.all - множественный promises завершенный агрегационный успех и отклонения

Сегодня кто-то поднял интересный случай с bluebird, как лучше всего обрабатывать несколько promises, где мы не заинтересованы останавливаться на данном выполнении или отклонении, а скорее заинтересованы в проверке окончательного результата. Пример:

var p1 = new Promise(function(f,r){
    setTimeout(function(){
        console.log("p1");
        f("yay");
    }, 100);

});

var p2 = new Promise(function(f,r){
    setTimeout(function(){
        console.log("p2");
        r(new Error("boo"));
    }, 200);

})

var p3 = new Promise(function(f,r){
    setTimeout(function(){
        console.log("p3");
        r(new Error("yay"));
    }, 300);

});

var p4 = new Promise(function(f,r){
    setTimeout(function(){
        console.log("p4");
        f("yay");
    }, 400);

});


//Promise.all([p1,p2, p3, p4]).then(function(p){
//    console.log("Results:",p);
//}).error(function(e){
//    console.log("Error:",e);
//});

Promise.map([p1,p2, p3, p4],function(p){
    console.log("results:",p);
}, {concurrency:10}).error(function(e){
    console.log("Error:",e);
});

Здесь, если мы запустим либо карту, либо все отклоненные promises вызовут, что обработчики не сообщают о результатах.

Например, результаты выполнения Promise.map, как реализовано выше:

debugger listening on port 65222
p1
results: yay
p2
Error: [Error: boo]
p3
p4

Process finished with exit code 0

Здесь код для каждого обещания выполняется, но сообщается только 1 результат и 1 ошибка. Ошибка приводит к остановке процесса.

Если мы раскомментируем, мы получим подобное поведение. На этот раз сообщается только об ошибке. Любые успехи не делают этого тогда (понятно).

debugger listening on port 65313
p1
p2
Error: [Error: boo]
p3
p4

Process finished with exit code 0

Учитывая такое поведение, какой был бы лучший способ реализовать сценарий, в котором выполняются все promises, и результаты выполненных promises сообщаются с любыми отказами?

Что-то вроде:

Promise.aggregate([p1,p2,p3,p4]).then(function(fulfilled, rejected){
    console.log(fulfilled); //all success
    console.log(rejected); //any and all rejections/exceptions
});
4b9b3361

Ответ 1

Вы использовали бы .reflect:

Promise.all([p1,p2,p3,p4].map(x => x.reflect()).then(results => {
  results.forEach(result => {
     if(result.isFulfilled()){
         // access result.value()
     } else {
         // access result.reason()
     }
  });
});

Это использовалось для функции settle, которая делала это для массива традиционно - она ​​была обобщена на .reflect, поскольку она отделяет агрегацию от понятия проверки обещаний и позволяет делать то, что .settle, но для других действий, таких как .any или .some.