2012-02-22 14 views
18

Sé que hay muchos control flow libraries para node.js. Algunos de ellos permiten una cadena de funciones de sincronización con devoluciones de llamadas (como async, asyncblock, etc.), los demás usan promise concept (Q, diferido, futuros, etc.). Dado un guión de ejecución prolongada, realizando una serie de acciones que pueden fallar en cualquier momento, ¿qué flujo de control preferirías y por qué? ¿Cuáles son los pros y los contras?Flujo de control de Node.js: devoluciones de llamada o promesas?

Respuesta

5

No creo que haya muchos pros y contras objetivos. Async es muy popular (basado en npm packages that depend on it).

Me gustan las bibliotecas de flujo de control (específicamente asíncronas), porque me es más fácil de entender. Las promesas me confunden, mientras que la asincrónica es fácilmente comprensible. Sin embargo, sospecho que es solo una curva de aprendizaje, y las promesas serían más legibles si gastara el esfuerzo en aprenderlas. ¿Pero debería esperar que la gente intente leer mi código también?

También hay un tercer tipo - Fibers. Fibers aún no funciona en Windows, pero (IMO) ofrece la sintaxis más clara para las cosas que deben ejecutarse en serie.

13

Pros de devoluciones de llamada:

  • simple de entender y crear.
  • Un poco más eficiente, porque se crean menos objetos y se recoge la basura.
  • Node optaron por (error,result) devoluciones de llamada en todo momento. Recomiendo seguir su orden de argumentos para coherencia. (A diferencia de decir (result1, result2, result3, error).)

Pros de promesas:

  • proporciona una interfaz fluida , que a veces puede ayudar a mitigar el infierno de devolución de llamada anidada, como shown here. El código parece fluir linealmente al encadenar llamadas .then(foo).then(bar).
  • Una buena biblioteca de promesas le permitirá ejecutar muchas operaciones asincrónicas en en paralelo, y continuar solo cuando estén completas. La biblioteca Deferred lo hace sin problemas a través de map, Q tiene allResolved y ES6 Promises ofrece Promise.all(). (Esto también es posible con devoluciones de llamadas, por ejemplo usando async.parallel(), pero no incorporado.)
  • Una biblioteca de buenas promesas le permitirá especificar una función de manejo de errores que se invocará si falla alguna de las funciones en cola. Para hacer esto con devoluciones de llamada se necesita un pequeño texto repetitivo: if (err) return callback(err); al comienzo de cada devolución de llamada.

No tendría sentido utilizar devoluciones de llamada cerca de la parte inferior de la pila, para el código que se ejecuta muchas veces por segundo. Más arriba en la pila, las promesas pueden ser preferibles ya que son más fáciles de leer y comprender, y pueden manejar los errores de forma más elegante.

Vale la pena señalar que las promesas se pueden generar a partir de las devoluciones de llamada en tiempo de ejecución. De modo que puede implementar su código central en el formulario de devolución de llamada minimalista, y aún así exponer una versión de promesas de la biblioteca si así lo desea. (Como en Q.nfbind().)

Me gustaría escuchar otros pros/contras. punta

Bono: Siempre maneje errores! Con ambos métodos, si no maneja el error, simplemente desaparecerá, dejándolo en la oscuridad acerca de por qué su código no funcionó como se esperaba.

devoluciones de llamada siempre debe manejar if (err) ... y promesas siempre debe tener un .catch() si no vuelven.

Incluso si espera errores a veces, y no necesita manejarlos, no manejar errores inesperados significa que no escuchará sobre errores de errores del desarrollador como errores tipográficos, si el código se cambia en el futuro.

Una alternativa a .catch() para Promises es escuchar unhandled rejections. Personalmente utilizo esto para emitir una advertencia de que .catch() faltaba.

+1

Más acerca de perfs: http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of/ – Offirmo

+0

El enlace ya no funciona – Shide

+1

Aquí está [una copia archivada de Enlace perf de Offirmo] (http://web.archive.org/web/20160522044854/http://thanpol.as/javascript/promises-a-performance-hits-you-should-be-aware-of). – joeytwiddle

0

He estado experimentando con un enfoque declarativo con esta biblioteca: http://chainsjs.org trabajo aún más que ver en él, sino que le da la capacidad de definir una "hoja de ejecución" donde se puede controlar casi por completo el flujo de de ejecución a partir de un mapeo simple.

+0

Ese sitio no funcionaba hoy, pero encontré [una copia] (http://web.archive.org/web/20141217011058/http://chainsjs.org/) en el archivo. Hay una lista de otras bibliotecas de flujo de control [aquí] (https://github.com/joyent/node/wiki/modules#user-content-wiki-async-flow). – joeytwiddle

+0

@joeytwiddle - gracias por la nota, nunca cambié el IP cuando las páginas de Github cambiaron de IP. Acabo de actualizar el DNS, debería ser una copia de seguridad pronto. –

Cuestiones relacionadas