D: Qual è il modo migliore in Node.js a 1) ottenere il risultato della prima chiamata asincrona, 2) scorrere l'elenco, rendendo più chiamate asincrone, e 3) elaborare i risultati quando Tutto è fatto".
Ci sono diversi approcci. Codifica delle mani, promesse, libreria asincrona. "Il meglio" è negli occhi di chi guarda, quindi non è proprio il caso di dirlo qui. Io uso Promises per tutta la mia codifica asincrona. Sono stati ufficialmente standardizzati in ES6 e ci sono buone e robuste implementazioni (mi piace Bluebird per le caratteristiche extra che ha oltre lo standard che semplificano le complesse attività asincrone e per la sua funzione promisifyAll()
che ti offre un'interfaccia promettente su qualsiasi operazione asincrona standard che usi la convenzione chiamata callback asincrono).
Mi sconsiglio di codificare a mano complicate operazioni asincrone perché la gestione degli errori è molto difficile e le eccezioni possono essere silenziosamente consumate all'interno di richiami asincroni che portano alla gestione degli errori persi e al debugging difficile. La libreria Async è probabilmente il miglior modo non promettente di fare le cose in quanto fornisce alcune funzionalità di infrastruttura e sincronizzazione attorno a callback asincroni.
Personalmente preferisco le promesse. Penso che vedremo più API asincrone che si standardizzano sulla restituzione di una promessa con il passare del tempo, quindi penso che sia una scelta migliore per un modo lungimirante di apprendere e programmare.
Q: Le promesse sono una buona scelta qui?
Sì, promesse permettono di eseguire una serie di operazioni asincrone e quindi utilizzare qualcosa come Promise.all()
sapere quando sono tutti fatti. Raccoglierà anche tutti i risultati di tutte le operazioni asincrone per te.
Q: È stata fatta()/successiva() un'opzione?
io non sono esattamente sicuro di quello che stai chiedendo circa qui, ma è possibile manualmente le operazioni asincrone codice a uno in parallelo e sapere quando sono fatto o per eseguirli in sequenza e sapere quando sono fatto. Le promesse fanno molto di più di questo lavoro per te, ma puoi farlo manualmente senza di loro.
D: Esiste un "linguaggio standard" in Node.js per questo tipo di scenario?
Se si utilizzano le promesse, ci sarebbe un modo comune per farlo. Se non si utilizzano le promesse, probabilmente non esiste un "linguaggio standard" in quanto vi sono molti modi diversi per codificarlo autonomamente.
Attuazione Promessa
Ecco un esempio utilizzando la libreria Bluebird Promessa in node.js:
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id);
})
}).then(function(results) {
// array of results here
}, function(err) {
// error here
});
});
Ecco come funziona:
Promisify l'oggetto di connessione in modo che tutti i suoi metodi hanno una versione che restituisce una promessa (basta aggiungere "Async" alla fine del metodo per chiamare questo ballo di fine anno versione isificata).
chiamata getFolderItemsAsync()
e la sua promessa si risolverà con la result.entries
serie
Esegui una mappa di tale matrice, in esecuzione tutte le operazioni in parallelo e restituendo una promessa che si risolve con una serie di risultati ordinati quando tutte le operazioni sono fatti.
Il risultato effettivo per ogni voce viene raggiunto con connection.getFileInfoAsync()
.
Creare un gestore di risoluzione e un gestore di rifiuti. Se qualche errore si verifica in qualsiasi parte del processo, si propagherà al gestore di rifiuti. Se tutte le operazioni hanno esito positivo, l'ultimo gestore di risoluzione verrà chiamato con una serie ordinata di risultati.
La versione sopra riportata si interrompe se si verifica un errore e non si ottengono risultati diversi dal codice di errore. Se si desidera continuare con un risultato null
se c'è un errore, allora si può usare qualcosa di simile:
var Promise = require('bluebird');
var connection = Promise.promisifyAll(box.getConnection(req.user.login));
connection.ready(function() {
connection.getFolderItemsAsync(0, null).then(function(result) {
return Promise.map(result.entries, function(item) {
return connection.getFileInfoAsync(item.id).catch(function(err){
// post the results as null and continue with the other results
return null;
});
})
}).then(function(results) {
// array of results here (some might be null if they had an error)
}, function(err) {
// error here
});
});
manualmente Coded Versione
Ecco una versione in codice manualmente. La chiave per questo sta rilevando quando il tuo ciclo asincrono è fatto confrontando if (results.length === result.entries.length)
. Nota: questo ha una gestione degli errori incompleta che è una delle difficoltà di codifica manuale e non utilizza una struttura asincrona come le promesse.
var connection = box.getConnection(req.user.login);
connection.ready(function() {
connection.getFolderItems(0, null, function (err, result) {
if (err) {
// do error handling here
opts.body = err;
} else {
var results = [];
for (var i = 0; i < result.entries.length; i++) {
connection.getFileInfo(result.entries[i].id, function (err, fileInfo) {
if (err) {
// do error handling here
opts.body = err;
results.push(null);
} else {
results.push(fileInfo);
}
// if done with all requests
if (results.length === result.entries.length) {
// done with everything, results are in results
// process final results here
}
});
}
}
});
});
Tutte le risposte che ho ricevuto sono stati grandi - grazie! Ho finito con l'uso asincrono, come suggerito da te e JasonWihardja. Ecco un buon tutorial: http://justinklemm.com/node-js-async-tutorial/ – paulsm4
Continuo a pensare che le promesse siano in definitiva il modo più idiomatico di farlo, ma sono contento che tu l'abbia trovato utile. – skarface