2016-06-13 15 views
1

Ich versuche, eine Funktion zu schreiben, die ihren Wert nicht zurückgibt, bis ein Versprechen in der Funktion aufgelöst wurde. Hier ist ein vereinfachtes Beispiel für das, was ich versuche zu tun.Wie warten Sie darauf, einen Wert zurückzugeben, bis das Versprechen gelöst ist?

Es ist eine Funktion, die eine Gruppen-ID anfordert und die Daten für diese Gruppe zurückgibt. Dabei werden auch die Namen der Benutzer in die Datenstruktur eingefügt, um ihre Namen anstelle ihrer Benutzer-ID anzuzeigen. Mein Problem ist, dass es asynchron läuft und die .then Rückrufe überspringt. Bis es zurückkommt g wurde keiner der Callbacks aufgerufen und g.memberNames ist noch leer. Gibt es eine Möglichkeit, die Funktion so lange warten zu lassen, bis alle Callbacks aufgerufen wurden?

Ich habe eine Menge Zeugs gesehen. Ist das hier notwendig? Es ist höchst unerwünscht, meinem Projekt andere Bibliotheken hinzuzufügen.

+0

Ich denke, der bevorzugte Weg, dies zu tun ist, einen Rückruf an Ihre Funktion übergeben, die, wenn sie bereit genannt werden. –

+0

Es wäre besser, die Idee, einen Wert synchron zurückzugeben, aufzugeben. Ihre Datenbank-API stellt Versprechungen bereit, verwenden Sie sie daher und versuchen Sie nicht, etwas Synchrones zu erreichen. Sie können alles schreiben, was Sie möchten, indem Sie sich an das asynchrone/Versprechen-Muster halten. Es ist wichtig, den Standpunkt zu ändern. – trincot

Antwort

2

Da Ihr Betrieb alle Profilnamen zurückzukehren ist auch Asynchron Sie ein Versprechen erfüllt zurückkehren sollte, wenn alle anderen Asynchron-Vorgänge abgeschlossen (oder ablehnen, wenn einer von ihnen abgelehnt wird) mit Promise.all

function get(db, id) { 
    let p = db.command('GET', 'group:${id}'); 
    return p.then(g => { 
    return Promise.all(g.members.map(id => { 
     // NOTE: id is shadowing the outer function id parameter 
     return User.get(db, id).then(profile => profile.name) 
    }) 
    }) 
} 
+0

Das ist genau das, was ich will. Vielen Dank. – rangeme

0
getan

Gibt es eine Möglichkeit, die Funktion warten zu lassen, g zurückzugeben, bis alle Rückrufe aufgerufen wurden?

Ja, gibt es. Aber du solltest deine Denkweise ändern von "warte bis alle Callbacks" aufgerufen wurden bis "warte bis alle Versprechen erfüllt sind". Und in der Tat, die Promise.all Funktion trivialerweise das - es braucht ein Array von Versprechen und gibt ein neues Versprechen, das mit einem Array der Ergebnisse löst.

In Ihrem Fall wäre es

sein
function get(db, id) { 
    return db.command('GET', 'group:${id}').then(g => { 
     var promises = g.members.map(id => { 
//        ^^^ never use `forEach` 
      return User.get(db, id).then(profile => profile.name); 
//   ^^^^^^ a promise for the name of that profile 
     }); 
     // 
     return Promise.all(promises).then(names => { 
//         ^^^^^^^^^^ fulfills with an array of the names 
      g.memberNames = names; 
      return g; 
     }); 
    }); 
}