¿Cuál es la forma correcta de encadenar llamadas asíncronas en javascript?
node.js titanium (1)
Estoy tratando de encontrar la mejor manera de crear llamadas asíncronas cuando cada llamada depende de la llamada anterior que se haya completado. En este momento estoy encadenando los métodos llamando recursivamente a una función de proceso definida como se ilustra a continuación.
Esto es lo que estoy haciendo actualmente.
var syncProduct = (function() {
var done, log;
var IN_CAT = 1, IN_TITLES = 2, IN_BINS = 3;
var state = IN_CAT;
var processNext = function(data) {
switch(state) {
case IN_CAT:
SVC.sendJsonRequest(url("/api/lineplan/categories"), processNext);
state = IN_TITLES;
break;
case IN_TITLES:
log((data ? data.length : "No") + " categories retrieved!");
SVC.sendJsonRequest(url("/api/lineplan/titles"), processNext);
state = IN_BINS;
break;
case IN_BINS:
log((data ? data.length : "No") + " titles retrieved!");
SVC.sendJsonRequest(url("/api/lineplan/bins"), processNext);
state = IN_MAJOR;
break;
default:
log((data ? data.length : "No") + " bins retrieved!");
done();
break;
}
}
return {
start: function(doneCB, logCB) {
done = doneCB; log = logCB; state = IN_CAT;
processNext();
}
}
})();
Entonces llamaría a esto como sigue
var log = function(message) {
// Impl removed.
}
syncProduct.start(function() {
log("Product Sync Complete!");
}, log);
Si bien esto funciona perfectamente bien para mí, no puedo evitar pensar que tiene que haber una manera mejor (más simple). ¿Qué pasa después cuando mis llamadas recursivas son demasiado profundas?
NOTA : no estoy usando javascript en el navegador, sino de forma nativa en el marco de Titanium, esto es similar a Javascript para Node.js.
Hay muchas bibliotecas y herramientas que hacen el encadenamiento asíncrono y el flujo de control para usted y en su mayoría vienen en dos sabores principales:
Bibliotecas de flujo de control
Por ejemplo, vea async , seq y step (basado en devolución de llamada) o Q y futures (basado en promesa). La principal ventaja de estos es que son solo bibliotecas JS sin formato que facilitan el dolor de la programación asíncrona.
En mi experiencia personal, las bibliotecas basadas en promesas tienden a conducir a un código que se parece más al código sincrónico habitual, ya que usted devuelve valores usando "retorno" y ya que los valores de promesas pueden pasarse y almacenarse, de manera similar a los valores reales.
Por otro lado, el código basado en la continuación es un nivel más bajo, ya que manipula explícitamente las rutas de los códigos. Posiblemente, esto puede permitir un flujo de control más flexible y una mejor integración con las bibliotecas existentes, pero también puede llevar a un código más intuitivo y placentero.
Compiladores de Javascript CPS
Extender el lenguaje para agregar soporte nativo para coroutines / generators le permite escribir código asíncrono de una manera muy sencilla y jugar bien con el resto del lenguaje, lo que significa que puede usar Javascript if enunciados, bucles, etc. en lugar de tener que replicarlos con funciones. Esto también significa que es muy fácil convertir el código de sincronización anterior en una versión asíncrona. Sin embargo, existe la desventaja obvia de que no todos los navegadores ejecutarán su extensión Javascript, por lo que deberá agregar un paso de compilación en su proceso de compilación para convertir su código a JS regular con devoluciones de llamada en el estilo de paso continuo. De todos modos, una alternativa prometedora son los generadores en la especificación Ecmascript 6, mientras que solo Firefox los admite de forma nativa a partir de ahora, hay proyectos como el regenerator y Traceur para compilarlos de nuevo a devoluciones de llamada. También hay otros proyectos que crean su propia sintaxis asíncrona (ya que los generadores de es6 no habían aparecido en ese entonces). En esta categoría, encontrarás cosas como tamejs y Iced Coffeescript . Finalmente, si usas Node.js allí también puedes echar un vistazo a Fibers .
Mi recomendación:
Si solo desea algo simple que no complique su proceso de construcción, le recomendaría ir con la biblioteca de flujo de control que mejor se adapte a su estilo personal y las bibliotecas que ya utiliza.
Sin embargo, si espera escribir muchos códigos asíncronos complicados y profundamente integrados, le recomendaría encarecidamente que al menos busque en una alternativa basada en compilador.