2017-10-31 3 views
2

Angenommen, newsService.getNews() gibt eine Zusage zurück, die in einen zufälligen Nachrichteneintrag aufgelöst werden sollte, der von einem Dienst zurückgegeben wird, während translateService.translate() ein Versprechen zurückgibt, das zur Übersetzung der Text wurde übergeben.Warten Sie, bis alle verschachtelten Versprechen abgeschlossen sind, aber immer noch auf jede einzelne Lösung reagieren

var newsPromises = []; 
var translatePromises = []; 
for (var i = 0; i < 5; i++) { 
    var p1 = this.newsService.getNews(); 
    newsPromises.push(p1); 

    p1.then(function (data) { 
     var p2 = this.translateService.translate(data); 
     translatePromises.push(p2); 
     p2.then(function (translatedData) { 
      addNews(`${data} (${translatedData})`); 

     }, function (fail) { 
      console.log(fail.message); 
     }); 

    }, function (fail) { 
     console.log(fail.message); 
    }); 
} 

jetzt die Seite zeigt zunächst eine Lade Spinner, die Ich mag würde die Versprechungen verstecken, wenn alle (einschließlich der verschachtelten Übersetzung Versprechen) abgeschlossen haben (erfolgreich oder nicht):

Promise.all(newsPromises) 
     .then(function (results) { 
      Promise.all(translatePromises).then(function (results) { 
        removeLoading(); 
       }, 
       function (err) { 
        removeLoading(); 
       } 
      ); 

     }, function (err) { 
      Promise.all(translatePromises).then(function (results) { 
        removeLoading(); 
       }, 
       function (err) { 
        removeLoading(); 
       } 
      ); 
     }); 

Dieser Code ein) funktioniert nicht so, wie es sollte, da der Ladespinner einige Male verschwindet, bevor die Versprechen gelöst werden, und b) schrecklich komplex ist.

Wie wird das richtig gemacht? (Mit Vanille JS/ES6)

Antwort

1

daran erinnern, dass verspricht Ketten Pipelines sind, wobei jeder Handler Ergebnis ist die Kette Transformation kann als das Ergebnis durch die Behandlungsroutine übergibt. Siehe Anmerkungen:

// We only need one array of promises 
const promises = []; 
// Build the array 
for (let i = 0; i < 5; i++) { 
    // Add this promise to the array 
    promises.push(
     // Get the news... 
     this.newsService.getNews().then(
      // ...and translate it... 
      data => this.translateService.translate(data) 
       .then(translatedData => { 
        // ...and show it as soon as it's available 
        addNews(`${data} (${translatedData})`); 
        // Note that here we're converting the resolution value to 
        // `undefined`, but nothing uses it so... 
        // If you want something to be able to use it, 
        // return `translatedData` (or `data` or...) 
       }) 
     ) 
     .catch(fail => { 
      console.log(fail.message); 
      // WARNING: Here you're converting rejection to resolution with `undefined` 
     }) 
    ); 
} 
// Wait until all that is done before removing the loading indicator 
Promise.all(promises).then(removeLoading); 

Beachten Sie, dass der einzige Grund, warum wir ist kein catch auf dem Promise.all Versprechen müssen, dass Sie (außer Protokollierung) Fehler sind zu ignorieren, die auftreten, so dass wir wissen, dass Versprechen nie ablehnen.

Beachten Sie auch, dass das obige davon ausgeht, dass removeLoading keine Aufmerksamkeit auf die Argumente, die es erhält, und dass es keine Versprechen zurückweist, die möglicherweise zurückweisen. Wenn es um Argumente schert und es ist wichtig, es ohne Argumente aufrufen, ändern Sie die Promise.all Bit:

Promise.all(promises).then(() => removeLoading()); 

Wenn es ein Versprechen zurückgibt, die ablehnen, müssen Sie einen catch Handler als auch.

0

in solchen Fällen die Schaffung i globalen Zähler loadersCount = 0

jedes Mal, wenn this.newsService.getNews() Funktionsaufruf rufen loaderStart()

und jedes Mal, wenn Sie addNews() oder console.log(fail.message) Anruf rufen loaderStop()

function loaderStart() { 
    if (loadersCount === 0) { 
    addLoading(); 
    } 
    loadersCount++; 
} 

function loaderStop() { 
    if (loadersCount === 1) { 
    removeLoading(); 
    } 
    loadersCount--; 
} 
Verwandte Themen