Ecco come penso che dovresti fare.
spezzare la catena
Poiché entrambe le funzioni useranno amazingData , ha senso averle in una funzione dedicata. Di solito lo faccio ogni volta che voglio riutilizzare alcuni dati, quindi è sempre presente come funzione arg.
Poiché il tuo esempio esegue del codice, suppongo che sia tutto dichiarato all'interno di una funzione. Lo chiamerò toto () . Quindi avremo un'altra funzione che verrà eseguita sia afterSomething () che afterSomethingElse () .
function toto() {
return somethingAsync()
.then( tata );
}
Noterai anche che ho aggiunto una dichiarazione di ritorno poiché di solito è la strada da percorrere con Promises: restituisci sempre una promessa in modo che possiamo continuare a concatenare se necessario. Qui, somethingAsync () produrrà amazingData e sarà disponibile ovunque all'interno della nuova funzione.
Ora, ciò che questa nuova funzione apparirà in genere dipende da processAsync () anche asincrono ?
processAsync non asincrono
Nessun motivo per complicare eccessivamente le cose se processAsync () non è asincrono. Qualche vecchio buon codice sequenziale ce l'avrebbe fatta.
function tata( amazingData ) {
var processed = afterSomething( amazingData );
return afterSomethingElse( amazingData, processed );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
Nota che non importa se afterSomethingElse () sta facendo qualcosa di asincrono o meno. In caso affermativo, verrà restituita una promessa e la catena potrà continuare. In caso contrario, verrà restituito il valore del risultato. Ma poiché la funzione viene chiamata da then () , il valore verrà comunque racchiuso in una promessa (almeno in Javascript grezzo).
processAsync asynchronous
Se processAsync () è asincrono, il codice avrà un aspetto leggermente diverso. Qui consideriamo afterSomething () e afterSomethingElse () non verranno riutilizzati da nessun'altra parte.
function tata( amazingData ) {
return afterSomething()
.then( afterSomethingElse );
function afterSomething( ) {
return processAsync( amazingData );
}
function afterSomethingElse( processedData ) {
}
}
Come prima per afterSomethingElse () . Può essere asincrono o no. Verrà restituita una promessa o un valore racchiuso in una promessa risolta.
Il tuo stile di codifica è abbastanza vicino a quello che faccio io, ecco perché ho risposto anche dopo 2 anni. Non sono un grande fan delle funzioni anonime ovunque. Trovo difficile leggere. Anche se è abbastanza comune nella comunità. È come abbiamo sostituito l' inferno di richiamo con un purgatorio di promesse .
Mi piace anche mantenere il nome delle funzioni nell'allora breve. Verranno comunque definiti solo localmente. E la maggior parte delle volte chiameranno un'altra funzione definita altrove - così riutilizzabile - per fare il lavoro. Lo faccio anche per le funzioni con un solo parametro, quindi non è necessario inserire e rimuovere la funzione quando aggiungo / rimuovo un parametro alla firma della funzione.
Esempio di cibo
Ecco un esempio:
function goingThroughTheEatingProcess(plenty, of, args, to, match, real, life) {
return iAmAsync()
.then(chew)
.then(swallow);
function chew(result) {
return carefullyChewThis(plenty, of, args, "water", "piece of tooth", result);
}
function swallow(wine) {
return nowIsTimeToSwallow(match, real, life, wine);
}
}
function iAmAsync() {
return Promise.resolve("mooooore");
}
function carefullyChewThis(plenty, of, args, and, some, more) {
return true;
}
function nowIsTimeToSwallow(match, real, life, bobool) {
}
Non concentrarti troppo su Promise.resolve () . È solo un modo rapido per creare una promessa risolta. Quello che cerco di ottenere con questo è avere tutto il codice che sto eseguendo in un'unica posizione, appena sotto i thens . Tutte le altre funzioni con un nome più descrittivo sono riutilizzabili.
Lo svantaggio di questa tecnica è che definisce molte funzioni. Ma è un dolore necessario, temo, per evitare di avere funzioni anonime ovunque. E comunque qual è il rischio: uno stack overflow? (scherzo!)
Anche l'uso di array o oggetti come definiti in altre risposte funzionerebbe. Questa in un certo senso è la risposta proposta da Kevin Reid .
Puoi anche usare bind () o Promise.all () . Nota che ti chiederanno comunque di dividere il tuo codice.
utilizzando bind
Se vuoi mantenere le tue funzioni riutilizzabili ma non hai davvero bisogno di mantenere ciò che è all'interno di allora molto breve, puoi usare bind () .
function tata( amazingData ) {
return afterSomething( amazingData )
.then( afterSomethingElse.bind(null, amazingData) );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( amazingData, processedData ) {
}
Per mantenerlo semplice, bind () anteporrà l'elenco di argomenti (eccetto il primo) alla funzione quando viene chiamata.
utilizzando Promise.all
Nel tuo post hai menzionato l'uso di spread () . Non ho mai usato il framework che stai usando, ma ecco come dovresti essere in grado di usarlo.
Alcuni credono che Promise.all () sia la soluzione a tutti i problemi, quindi credo che meriti di essere menzionato.
function tata( amazingData ) {
return Promise.all( [ amazingData, afterSomething( amazingData ) ] )
.then( afterSomethingElse );
}
function afterSomething( amazingData ) {
return processAsync( amazingData );
}
function afterSomethingElse( args ) {
var amazingData = args[0];
var processedData = args[1];
}
Puoi passare i dati a Promise.all () - nota la presenza dell'array - purché promesse, ma assicurati che nessuna delle promesse fallisca altrimenti si interromperà l'elaborazione.
E invece di definire nuove variabili dall'argomento args , dovresti essere in grado di usare spread () invece di then () per ogni tipo di lavoro fantastico.