Promise.all — подождите, пока все уладятся, даже если часть из них будет отклонена

У меня есть массив промисов, которые я хочу выполнять параллельно.

  1. Я хочу дождаться, пока они все осядут, прежде чем что-то делать.
  2. После того, как все они будут улажены, я хочу предпринять некоторые действия.

Я хочу знать, если какой-либо из них отклонен. Однако, даже когда некоторые обещания отвергаются, я все равно хочу, чтобы другие были выполнены.

Хотите сделать это со встроенными промисами в ES6, а не с какими-то специальными библиотеками, такими как Q, When, WinJS, CO и т. д.

Вот конкретный пример. При этом я хочу знать, что все 8 URL-адресов из раунда 1 завершены (2 неудачно, 6 успешно), прежде чем переходить к URL-адресам в раунде 2.

Что происходит, так это то, что как только любое из обещаний отклоняется, управление переходит к первому блоку catch и продолжает цепочку затем.

"use strict";

var request = require('request');
var util = require('util');

function getPage(url){
    return new Promise(function(resolve,reject){
        request(url, function(error, response, body){
            if(!error && response.statusCode == 200){
                let result = util.format('Done with %s, %d bytes', url, body.length);
                console.log(result);
                resolve(result);
            }
            else{
                reject(Error(error));
            }
        })
    });
}

let round1 = ['http://www.google.com', 'http://www.yahoo.com', 'http://www.nytimes.com', 'http://www.wsj.com', 'http://www.bad1ffsdwre.com', 'http://www.cnn.com', 'http://www.bad2ffsdwre.com', 'http://www.msnbc.com'];
let round2 = ['http://www.facebook.com', 'http://www.twitter.com', 'http://www.snapchat.com', 'http://www.instagram.com'];

Promise.all(round1.map(getPage))
    .then(function(results){
        console.log('Successfully completed Round1');       
    })
    .catch(function(error){
        console.log('there is an error in round 1: ', error);       
    })
    .then(function(){
        console.log('Done with Round 1')
    })
    .then(function(){
        Promise.all(round2.map(getPage))
            .then(function(results){
                console.log('Done with Round2');        
            })
            .catch(function(error){
                console.log('there is an error in round 2', error);     
            })          
    });

Фактический результат:

node promises.js                                                                    
there is an error in round 1:  [Error: Error: getaddrinfo ENOTFOUND www.bad1ffsdwre.com www.bad1ffsdwre.com:80]    
Done with Round 1                                                                                                  
Done with http://www.google.com, 50085 bytes                                                                       
Done with http://www.cnn.com, 106541 bytes                                                                         
Done with http://www.snapchat.com, 6320 bytes                                                                      
Done with http://www.instagram.com, 14707 bytes                                                                    
Done with http://www.msnbc.com, 139798 bytes                                                                       
Done with http://www.facebook.com, 34710 bytes                                                                     
Done with http://www.nytimes.com, 177062 bytes                                                                     
Done with http://www.wsj.com, 827412 bytes                                                                         
Done with http://www.yahoo.com, 632892 bytes                                                                       
Done with http://www.twitter.com, 260178 bytes                                                                     
Done with Round2 

Желаемый результат:

node promises.js                                                                    
there is an error in round 1:  [Error: Error: getaddrinfo ENOTFOUND www.bad1ffsdwre.com www.bad1ffsdwre.com:80]    
Done with http://www.google.com, 50085 bytes                                                                       
Done with http://www.cnn.com, 106541 bytes                                                                         
Done with http://www.msnbc.com, 139798 bytes                                                                       
Done with http://www.nytimes.com, 177062 bytes                                                                     
Done with http://www.wsj.com, 827412 bytes                                                                         
Done with http://www.yahoo.com, 632892 bytes
there is an error in round 1:  [Error: Error: getaddrinfo ENOTFOUND www.bad2ffsdwre.com www.bad2ffsdwre.com:80]
Done with Round 1 
Done with http://www.snapchat.com, 6320 bytes                                                                      
Done with http://www.instagram.com, 14707 bytes                                                                    
Done with http://www.facebook.com, 34710 bytes                      
Done with http://www.twitter.com, 260178 bytes                                                                     
Done with Round2 

Я пытаюсь изучить шаблоны простых обещаний ES6, как описано в этой отличной статье< /а>. Нечто подобное автор упоминает и в этой цитате чуть ли не в самом конце статьи.

Примечание. Я не уверен в полезности Promise.race; Я бы предпочел иметь противоположность Promise.all, которая отклоняется только в том случае, если все элементы отклоняются.


person Amit Kulkarni    schedule 18.05.2016    source источник
comment
Да, это действительно дубликат этого: (stackoverflow.com/questions/31424561/).   -  person Amit Kulkarni    schedule 18.05.2016
comment
Для тех, кто склонен, вот суть, в которой есть решение для конкретного примера, указанного в вопросе: .com/arkulkarni/477bacef563166d639112f6ecd13f63a   -  person Amit Kulkarni    schedule 18.05.2016
comment
Также вот еще одна суть, реализующая решение с использованием генераторов и yield для справки:   -  person Amit Kulkarni    schedule 18.05.2016