Acabo de comenzar a usar el nodo, y una cosa que noté rápidamente es la rapidez con que las devoluciones de llamada pueden acumularse hasta un nivel tonto de sangría:
doStuff(arg1, arg2, function(err, result) {
doMoreStuff(arg3, arg4, function(err, result) {
doEvenMoreStuff(arg5, arg6, function(err, result) {
omgHowDidIGetHere();
});
});
});
La guía de estilo oficial dice que poner cada devolución de llamada en una función separada, pero eso parece demasiado restrictivo en el uso de cierres, y hacer que un solo objeto declarado en el nivel superior esté disponible varias capas hacia abajo, ya que el objeto debe pasar por todos los devoluciones de llamada intermedias.
¿Está bien usar el alcance de la función para ayudar aquí? ¿Coloca todas las funciones de devolución de llamada que necesitan acceso a un objeto global-ish dentro de una función que declara ese objeto, por lo que se cierra?
function topLevelFunction(globalishObject, callback) {
function doMoreStuffImpl(err, result) {
doMoreStuff(arg5, arg6, function(err, result) {
callback(null, globalishObject);
});
}
doStuff(arg1, arg2, doMoreStuffImpl);
}
y así sucesivamente para varias capas más ...
¿O existen marcos, etc. para ayudar a reducir los niveles de sangría sin declarar una función con nombre para cada devolución de llamada? ¿Cómo manejas la pirámide de devolución de llamada?
fuente
Respuestas:
Hay múltiples implementaciones de "promesas":
Por ejemplo, puede reescribir estas devoluciones de llamada anidadas
me gusta
En lugar de devolución de llamada en devolución de llamada,
a(b(c()))
se encadena el ".then"a().then(b()).then(c())
.Una introducción aquí: http://howtonode.org/promises
fuente
Como alternativa a las promesas, debe echar un vistazo a la
yield
palabra clave en combinación con las funciones del generador que se presentarán en EcmaScript 6. Ambas están disponibles hoy en las compilaciones Node.js 0.11.x, pero requieren que especifique adicionalmente el--harmony
indicador cuando ejecute Node .js:El uso de estos constructos y una biblioteca como la de TJ Holowaychuk co le permiten escribir código asíncrono en un estilo que se ve como el código sincrónico, a pesar de que aún se ejecuta de forma asíncrona. Básicamente, estas cosas juntas implementan el soporte de rutina para Node.js.
Básicamente, lo que debe hacer es escribir una función generadora para el código que ejecuta cosas asincrónicas, llamar a las cosas asíncronas allí, pero prefijarlas con la
yield
palabra clave. Entonces, al final su código se ve así:Para ejecutar esta función de generador, necesita una biblioteca como la mencionada anteriormente co. La llamada se ve así:
O, para ponerlo en línea:
Tenga en cuenta que desde las funciones del generador puede llamar a otras funciones del generador, todo lo que necesita hacer es prefijarlas
yield
nuevamente.Para una introducción a este tema, busque en Google términos como
yield generators es6 async nodejs
y debería encontrar toneladas de información. Lleva un tiempo acostumbrarse, pero una vez que lo consigues, no querrás volver nunca más.Tenga en cuenta que esto no solo le proporciona una sintaxis más agradable para llamar a las funciones, sino que también le permite utilizar la lógica de flujo de control habitual (sincrónica), como
for
bucles otry
/catch
. No más perder el tiempo con muchas devoluciones de llamada y todas estas cosas.Buena suerte y diviertete :-)!
fuente
Ahora tiene el paquete asyncawait , con una sintaxis muy cercana a lo que debería ser el futuro soporte nativo de
await
&async
in Node.Básicamente, le permite escribir código asíncrono que parece síncrono , reduciendo drásticamente los niveles de sangría y LOC, con la compensación de una ligera pérdida de rendimiento (los números del propietario del paquete tienen una velocidad del 79% en comparación con las devoluciones de llamadas sin procesar), con suerte reducido cuando el soporte nativo estará disponible.
Sigue siendo una buena opción para salir del callback hell / pyramid of doom nightmare IMO, cuando el rendimiento no es la principal preocupación y el estilo de escritura sincronizada se adapta mejor a las necesidades de su proyecto.
Ejemplo básico del paquete doc:
fuente