2016-04-11 8 views
2

Also habe ich ein Problem mit JavaScript Promises. Ich verwende native Implementierung, um Abhängigkeiten zu reduzieren.Wie man promise.all auf verschachtelte provect.all warten?

Ein illustratives Beispiel für das, was ich brauche.

Ich muss Listen von Büchern, Buchautoren und Käufe abrufen. Ich brauche auch ein Autorenprofil für jeden der Autoren. Nachdem ich all das bekommen habe, muss ich eine nette Sammlung von Autoren mit ihren Büchern und der Einkaufsliste für jedes der Bücher erstellen.

Listen und Profile sind separate API JSON-Aufrufe. Die einzige Abhängigkeit besteht darin, dass ich eine Liste von Autoren benötige, um Autorenprofile zu erhalten.

Ich habe das mit Promises gelöst. Ich verwende Promise.all, um 3 API JSON-Anfragen für Autoren, Bücher und Käufe zu erhalten. Ich benutze noch eine weitere Promise.all, um alle Profile für jeden der Autoren zu bekommen, die ich bekomme (ich durchlaufe die Liste, mappe URLs für jedes Profil und sende einen Stapel von Anfragen parallel).

Ich führe den Profilantrag Batch sobald ich die Liste der Autoren bekomme, also im "Then" -Handler der Autorenliste zu versprechen.

Nun das Problem:

Um sicher zu sein, dass alle Versprechungen, 3-Listen und alle Profile werden vor meiner Montage der Bibliothek Satzes erfolgen, müsste ich ein Profil Charge von Anfragen senden wenn ich mit allen Listen fertig bin, im ersten Promise.all Then-Handler.

Aber: Bücher Bücher ein Käufe nehmen viel mehr Zeit als die Liste der Autoren und ich möchte nicht auf alle von denen zu senden eine Charge von Profilanforderungen warten, also sende ich es im Then - Handler der Autor-Liste Versprechen, damit diese beginnen, sobald ich die Informationen habe.

Ein verschachteltes Promise.all zählt jedoch nicht zu seinem übergeordneten Promise.all Then-Handler, also da meine FinalFunction im Then des Top-Level-Promise.all ist, kann es (und manchmal auch) vor dem Nested feuern Promise.all hat alle Autorenprofile abgerufen.

Ich muss in der Lage sein, alle Promise-Anfragen so schnell wie möglich zu starten, aber nur der Stapel der Autor-Anfragen hängt davon ab, dass ein Versprechen abgeschlossen ist, also muss ich darauf warten. Alle anderen sollten unabhängig voneinander starten.

Pseudo-Code

Promise.all(
    requestBooks().then(){}, 
    requestAuthors().then(){ 
    GenerateArrayOfAuthorUris(); 
    // now send a promisifyed batch of per-author requests 
    Promise.all(
     [array of author uris to run requests for] 
    ) 
    .then(){ 
     // If I run this here, I may not have upper-level requests done 
     runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
    } 
    }, 
    requestPurchases().then(){}, 
) 
.then(){ 
    // this will fire when 3 top requests are done, but won't wait for 
    // the nested Promise.all with per-author requests 
    runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
} 

Wenn ich es auf diese Weise zu tun, ich bin durch das Warten auf Anfragen kostbare Zeit verschwenden muss ich Anfragen pro-Autor nicht warten nur auf Start:

Promise.all(
    requestBooks().then(){}, 
    requestAuthors().then(){ 
    GenerateArrayOfAuthorUris(); 
    }, 
    requestPurchases().then(){}, 
) 
.then(){ 
    // now send a promisifyed batch of per-author requests 
    Promise.all(
     [array of author uris to run requests for] 
    ) 
    .then(){ 
     // If I run this here, I may not have upper-level requests done 
     runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
    } 
} 

Hoffentlich klärt dies, was ich brauche.

Vielen Dank.

Dies ist der Code Beispiel: https://jsbin.com/qizohasofa/edit?js,console

+0

Das ist eine Menge Text und ich habe es (noch) nicht gelesen, aber aus dem Titel klingt es so, als ob du 'Return yourPromiseVar' irgendwo oder so ähnlich vermisst. Können Sie bitte mit Ihrem Code Geige erstellen (ersetzen Sie diese Anfragen mit einigen Timeouts)? – llamerr

+0

Es gibt jetzt eine aktualisierte Version. – Anthony

+0

Klingt so, als hätten Sie vergessen, ein Array-Literal um die "Promise.all" -Parameter zu erstellen, und vergessen, 'Versprechungen 'von' Then'-Callbacks zu wiederholen, die asynchrone Dinge tun. Es würde helfen, statt Pseudo-Code tatsächlich zu zeigen. – Bergi

Antwort

1

Wie Sie in den Kommentaren gesagt wurde, das hast du nicht return etwas von Ihren Funktionen, so hat then nicht wissen, was innere Versprechen zu warten.

function getJokeCategories() { 
    return Promise.all([ 
// ^^^^^^ 
     pgetJSON("http://api.icndb.com/categories"), 
     pgetJSON("http://api.icndb.com/jokes/count").then(function(data) { 
      var jokesToGet = []; 
      for (var i=0; i<data; i++){ 
       jokesToGet.push("http://api.icndb.com/jokes/"+i); 
      } 
      return Promise.all(jokesToGet.map(function(jk) { 
//   ^^^^^^ 
       return pgetJSON(jk).then(function(joke) { 
//    ^^^^^^ 
        console.log(jk + " just returned", joke); 
        return joke; 
//     ^^^^^^ 
       }); 
      })).then(function(jokes) { 
       console.log("All jokes returned. This does happen only when all jokes are retrieved."); 
       return {count:data, jokes:jokes}; 
//    ^^^^^^ 
      }); 
     }) 
    ]); 
} 
getJokeCategories().then(function(result) { 
    console.log(result, "This does happen at the very end when joke count, joke categories and all jokes are returned."); 
}); 
+0

Ich sehe und verstehe jetzt Kommentare. Ich musste von beiden Promise.alls und von jedem der Versprechen innerlich zurückkehren, um es zu arbeiten. Alles weniger als alles ist gescheitert. – Anthony

Verwandte Themen