Supponi di mantenere una libreria che espone una funzione getData
. Gli utenti chiamano per ottenere dati reali:
var output = getData();
Sotto il cofano i dati vengono salvati in un file in modo da implementato getData
utilizzando Node.js built-in fs.readFileSync
. È ovvio sia getData
e fs.readFileSync
sono funzioni di sincronizzazione. Un giorno ti è stato detto di cambiare l'origine dati sottostante in un repository come MongoDB a cui è possibile accedere solo in modo asincrono. Ti è stato anche detto di evitare di far incazzare i tuoi utenti, l' getData
API non può essere modificata per restituire semplicemente una promessa o richiedere un parametro di callback. Come soddisfi entrambi i requisiti?
La funzione asincrona che utilizza callback / promise è il DNA di JavasSript e Node.js. Qualsiasi app JS non banale è probabilmente permeata di questo stile di codifica. Ma questa pratica può facilmente portare alla cosiddetta piramide del richiamo del destino. Ancora peggio, se qualsiasi codice in un chiamante nella catena di chiamate dipende dal risultato della funzione asincrona, anche quel codice deve essere avvolto nella funzione di callback, imponendo un vincolo di stile di codifica al chiamante. Di tanto in tanto trovo la necessità di incapsulare una funzione asincrona (spesso fornita in una libreria di terze parti) in una funzione di sincronizzazione al fine di evitare un massiccio rifactoring globale. La ricerca di una soluzione su questo argomento di solito si è conclusa con Node Fibreso pacchetti npm derivati da esso. Ma le fibre non possono risolvere il problema che sto affrontando. Anche l'esempio fornito dall'autore di Fibers ha illustrato la carenza:
...
Fiber(function() {
console.log('wait... ' + new Date);
sleep(1000);
console.log('ok... ' + new Date);
}).run();
console.log('back in main');
Uscita effettiva:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
back in main
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
Se la funzione Fiber trasforma davvero la funzione sleep async in sync, l'output dovrebbe essere:
wait... Fri Jan 21 2011 22:42:04 GMT+0900 (JST)
ok... Fri Jan 21 2011 22:42:05 GMT+0900 (JST)
back in main
Ho creato un altro semplice esempio in JSFiddle e sto cercando il codice per produrre l'output previsto. Accetterò una soluzione che funziona solo in Node.js quindi sei libero di richiedere qualsiasi pacchetto npm nonostante non funzioni in JSFiddle.