2017-12-19 6 views
0

Ich habe eine Funktion requestJSON, die eine externe API abfragt und eine (Bluebird) Zusage zurückgibt.node.js + bluebird: auflösen promise.all

Problem:b aufgelöst wird, bevor c in die Liste aufgenommen wird, um die promise.all läuft, während nur a und b gelöst werden.

Code:

let promises = []; 
 

 
// push promise a 
 
promises.push(requestJSON(..)); 
 

 
// push promise b 
 
promises.push(requestJSON(..).then((response) { 
 
    // push promise c 
 
    promises.push(requestJSON({foo: response.bar}); 
 
}); 
 

 
promises.all((data) => { 
 
    console.log(data.length) // --> 2 
 
});

Frage: Ich konnte nicht mit einer wirklich befriedigenden Lösung für dieses Problem kommen. Gibt es einen Node-Way/Best-Practice?

Mögliche Lösungen

(I) Wickeln b in einem anderen Versprechen und lösen es innerhalb c.then.
Problem: Ein zusätzliches Versprechen, das nicht wirklich viel tut, außer den Code zu überfluten.

let promises = []; 
 

 
// push promise a 
 
promises.push(requestJSON(..)); 
 

 
// push helper promise 
 
promises.push(new Promise((resolve, reject) => { 
 
    // push promise b 
 
    promises.push(requestJSON(..).then((response) { 
 
    // push promise c 
 
    promises.push(requestJSON({foo: response.bar}); 
 
    // resolve helper promise 
 
    resolve(); 
 
    }).catch(..); 
 
})); 
 

 

 
promises.all((data) => { 
 
    console.log(data.length) // --> 4 
 
});

(II) Setzen Sie alles innerhalb b.then.
Problem: Es gibt keinen semantischen Grund, a und promise.all innerhalb b zu setzen + diese Lösung erinnert mich an die vorversprechende Callback-Wahnsinn.

let promises = []; 
 

 
// push promise b 
 
promises.push(requestJSON(..).then((response) { 
 
    // push promise a 
 
    promises.push(requestJSON(..)); 
 

 
    // push promise c 
 
    promises.push(requestJSON({foo: response.bar}); 
 
    
 
    promises.all((data) => { 
 
    console.log(data.length) // --> 3 
 
    }); 
 
});

Antwort

1

Sie müssen etwas von einem .then Rückruf zurück. Entweder ein Wert (dann gilt das Versprechen als gelöst) oder ein anderes Versprechen, wenn Sie weiter auf etwas anderes warten möchten.

let promises = [ 
    requestJSON(/* [1] */), 
    requestJSON(/* [2] */).then(response => { 
     return requestJSON(/* [3] */); 
    }) 
]; 

// this waits for [1] and [3] 
promises.all(promises).then(results => { 
    console.log(data.length); 
}); 

Ihr Code Rückkehr nichts von der .then(). Der Rückgabewert der Funktion ist also undefined und das Versprechen wird mit undefined als Ergebnis erledigt.

Das Obige kann wie (man beachte die impliziten return in Pfeil-Funktionen, die nicht mit einem vollen Körper) geschrieben werden:

let promises = [ 
    requestJSON(/* [1] */), 
    requestJSON(/* [2] */).then(response => requestJSON(/* [3] */)) 
]; 

promises.all(promises).then(results => console.log(data.length)); 
+0

wow, ich wusste nicht, dass Sie im Innern dann ein Versprechen zurückkehren könnten, dass du willst warten, danke! – Alex

+0

Ja, Sie können eine Kette bauen, die aus so vielen Versprechungen besteht, wie Sie möchten, und alle nacheinander auflösen. Eine Möglichkeit, dies zu verwenden, ist 'var p = dataArray.reduce ((Kette, Element) => asyncFunction (Element), Promise.resolve()); 'Dieses Daisy verkettet alle Elemente im Array, so dass sie alle verarbeitet werden der Reihe nach. Beginnt mit einem leeren Versprechen 'Promise.resolve()' und gibt ein einzelnes Versprechen 'p' zurück, das verrechnet wird, wenn das letzte Element fertig ist. – Tomalak

Verwandte Themen