2016-08-07 34 views
1

Momentan gibt dieser Code eine Null aus, weil das erste Versprechen im Array sofort verrechnet wird.Wie mit Versprechungen umzugehen, wie sie lösen?

const promises = []; 
 
const promiser = (number) => new Promise((resolve, reject) => window.setTimeout(() => resolve(number), number * 100)); 
 
for (let index = 0; index < 10; index++) { 
 
    const promise = promiser(index); 
 
    promises.push(promise); 
 
} 
 

 
Promise.race(promises).then(r => console.debug(r));

Ich bin auf der Suche zu machen, so dass, sobald die schnellsten Versprechen lösen, ist es aus dem promises Array und ein neuer Promise.race Anruf entfernt wird, wird mit den restlichen Versprechungen gemacht, bis keine Wiederholung Versprechen ist übrig.

Da Promise.race das Ergebnis des Versprechens zurückgibt, nicht das aufgelöste Versprechen selbst, obwohl ich nicht in der Lage bin zu identifizieren, welches Versprechen es war, das gelöst hat und ich nicht weiß, welches aus dem Array entfernt werden soll. Gibt es eine Möglichkeit, das zu wissen? Ich nehme an, ich könnte ein komplexes Objekt mit einer Art Korrelationsschlüssel und dem Ergebnis zurückgeben, aber das scheint seltsam. Ich hatte gehofft zweiten Parameter der Promise.race Callback wäre Index der Verheißung, aber das ist nicht der Fall, und es macht auch keinen Sinn, da die then ist nur eine then eines anderen Versprechen, also wie würde es wissen, dass es einige zurückgeben sollte Index sowieso. Kannst du dir einen besseren Weg vorstellen?

Auch ich alle Versprechen mit der ersten race laufen, aber das sollte kein Problem für die nachfolgende race s, oder? Falls in der Zwischenzeit ein anderes Versprechen gelöst wurde, bevor der folgende race Anruf getätigt wurde, sollte es einfach zurückgeben, kein Problem, richtig? Und wenn mehrere Versprechungen in der Zwischenzeit gelöst wurden, würde es einfach die erste (in Array-Reihenfolge oder in Auflösungsreihenfolge?) Zurückgeben und dann würde die nächste race die zweite zurückgeben und so weiter ... Richtig?

BTW Ich auch, obwohl ich das Array gehen und Versprechen entfernen konnte, die isResolved haben, aber das ist keine echte Sache. Selbst wenn dies der Fall wäre, würde dies für den Fall, dass mehrere Versprechungen zwischen den Aufrufen an race aufgelöst werden, vollständig unterbrochen werden.

+1

könnten Sie die Promises auf einen Wert auflösen, der das Versprechen sowie den Wert angibt, nach dem Sie suchen - im Fall Ihres Beispiels ist Ihr Wert der Index, es ist also ganz einfach, das zu tun, was Sie wollen Code –

+0

Versprechen.race() wird verwendet, wenn Sie nur an einer der Auflösungen interessiert sind. - Für die sequentielle Ausführung, fügen Sie nur .then() -Klauseln zu einem einzigen Versprechen, können Sie auch ein Versprechen in .then - Für die parallele Ausführung, verwenden Sie Promise.all wie Mattias Buelens Antwort –

Antwort

1

Sie eine Kennung für die Versprechen zurückgeben kann

const promises = []; 
const promiser = (number, id) => new Promise((resolve, reject) => window.setTimeout(() => resolve({ number, id }), number * 100)); 
for (let index = 0; index < 10; index++) { 
    const promise = promiser(index, "id_" + index); 
    promises.push(promise); 
} 

Promise.race(promises).then(r => console.debug(r.id)); 

Wie auch immer, wenn Sie mit dem Versprechen Bibliothek wie bluebird arbeiten Sie einen gewissen Nutzen finden können, die Sie Ihren Code strukturieren helfen kann, besser (wie Promise.reduce oder Promise.any)

+0

Danke, also im Grunde, was ich gesagt habe im mittleren Absatz. Das ist scheiße, weil ich das nicht mit Versprechen nutzen kann, die ich nicht kreiere. Ich werde in Bluebird schauen, um zu sehen, ob es meinen Bedürfnissen entspricht. –

+2

Sie können es mit Versprechen verwenden, die Sie nicht erstellen, indem Sie etwas in der Art von '.then verwenden (r => ({result: r, id: someIdentifier})) - und das ist das Versprechen, das Sie in die Array –

+1

Guter Punkt! BTW @drinchev Bluebird scheint sowohl 'each' als auch' reduce' sequenziell zu laufen, was saugt, denn für mich spielt es keine Rolle, in welcher Reihenfolge sich die Versprechen auflösen, ich muss sie so schnell wie möglich bearbeiten. Aber der Trick mit der ID, die du und @Jaromanda X vorgeschlagen hast, wird für mich funktionieren, danke nochmal. –

4

ich bin auf der Suche zu machen, so dass, sobald die schnellsten Versprechen lösen, ist es aus dem promises Array und ein neuer Promise.race Anruf wird mit den verbleibenden Versprechen entfernt wird, bis keine Wiederholung Versprechen ist übrig.

Warum wollen Sie Promise.race verwenden, wenn Sie schließlich alle Versprechen zu handhaben wollen? Kannst du nicht einfach jede Zusage bearbeiten, sobald sie gelöst ist, und dann warten, bis alle Versprechen erfüllt sind?

const promises = []; 
const promiser = (number) => new Promise((resolve, reject) => window.setTimeout(() => resolve(number), number * 100)); 

for (let index = 0; index < 10; index++) { 
    const promise = promiser(index) 
     .then(r => process(r)); // process every promise individually 
    promises.push(promise); 
} 

Promise.all(promises) // wait for all promises to be processed 
     .then(r => console.debug('all done!')); 

Oder ist processauch asynchron, und Sie müssen sicherstellen, dass nur ein Versprechen zu einem Zeitpunkt verarbeitet zu werden?

+0

Am Anfang wollte ich "Prozess" auch asynchron sein, also ja, aber da ich mein Problem weiter untersuche, stellt sich heraus, dass ich darauf verzichten kann, also hast du eigentlich recht! Ich werde die Antwort von @ drinchev beibehalten, wenn sie meine Frage beantwortet haben, wenn es Ihnen nichts ausmacht, aber Sie haben mir geholfen, zu sehen, dass ich die falsche Frage gestellt habe. Vielen Dank. –

+0

Dies ist die richtige Antwort. - Die drei Zeilen in der for-Schleife sollten ein einzelner Push-Ausdruck sein - Am Ende von Promise.all(). Then() sollte eine .catch-Anweisung hinzugefügt werden, die die erste Ablehnung oder Ausnahme erhält. –