JavaScript es un poderoso lenguaje de programación con su capacidad de cierre, funciones de primera clase y muchas otras características. JavaScript se usa a menudo para la programación asincrónica o la programación en un estilo que usa devoluciones de llamada. Si bien es poderoso, esto puede llevar a lo que muchos ahora denominan Callback HellEl infierno de devolución de llamada también se conoce cariñosamente como Pyramid Of Doom gracias a los muchos niveles de sangría que hacen que su código parezca una pirámide difícil de leer. Repasemos la evolución de la programación asincrónica en JavaScript de devoluciones de llamada a async / await, ya que esto nos ayudará en nuestra programación Node.js.


¿Para qué se utilizan las devoluciones de llamada de JavaScript?

Las funciones de devolución de llamada en JavaScript son funciones que se pueden pasar a otras funciones como parámetro. También se conocen como funciones de orden superior y se llaman (o ejecutan) dentro de la función a la que se pasaron. Una devolución de llamada es una convención, no una cosa real en el lenguaje JavaScript. Las devoluciones de llamada se utilizan cuando necesita hacer cosas en su código que resultan en operaciones de E / S o de entrada / salida. Cosas como hablar con una base de datos, descargar una foto o escribir un archivo en el disco son ejemplos de operaciones de E / S. Estas son operaciones asincrónicas. En otras palabras, pueden tomar algún tiempo o suceder en el futuro. Vea una función de devolución de llamada de ejemplo .

Veamos un ejemplo de código aquí.

¿Qué crees que pasará cuando se ejecute este código? Veamos.

express-rest $ node index.js
C: \ node \ express-rest \ index.js: 21
console.log (blogpost.title);
                     ^

TypeError: no se puede leer la propiedad 'título' de indefinido
    en Object. (C: \ node \ express-rest \ index.js: 21: 22)
    en Module._compile (module.js: 643: 30)
    en Object.Module._extensions..js (module.js: 654: 10)
    en Module.load (module.js: 556: 32)
    en tryModuleLoad (module.js: 499: 12)
    en Function.Module._load (module.js: 491: 3)
    en Function.Module.runMain (module.js: 684: 10)
    al inicio (bootstrap_node.js: 187: 16)
    en bootstrap_node.js: 608: 3

La aplicación dice que no puede leer una propiedad de undefined. ¿Pero por qué? JavaScript no espera a que se complete la operación asíncrona para seguir avanzando en la ejecución del código. Simplemente ejecuta cada línea del programa sin detenerse. En otras palabras, no bloquea. La función getBlogPost () se ejecuta inmediatamente y establece el valor de blogpostindefinido. Esta es la razón por la que se necesitan devoluciones de llamada al programar JavaScript y Node. Podemos reescribir este ejemplo usando una devolución de llamada para obtener el resultado que queremos.

js callback en acción

Esto está más en la línea de lo que estamos buscando. Iniciamos el programa, y ​​pasados ​​2 segundos vemos el resultado en pantalla.


Infierno de devolución de llamada

Pensemos en una situación que podría causar un infierno de devolución de llamada. Imagine en su aplicación que le gustaría buscar un usuario de la base de datos. Una vez que tenga ese usuario, ahora desea obtener todas las publicaciones de blog de ese usuario. Una vez que tenga las publicaciones del blog, también desea obtener los comentarios de esa publicación del blog. En un enfoque sincrónico, esto es bastante sencillo. En el mundo asincrónico, esto puede comenzar a causar algunos problemas. ¡El código resaltado aquí es lo que llamamos Pyramid Of Doom ! También podrías llamarlo infierno de devolución de llamada, pero la pirámide de la fatalidad suena tan asesina, ¡jaja!

Este código funciona, pero no es tan fácil de leer ni mirar. Peor aún, si sigue sangrando niveles adicionales de devoluciones de llamada, ciertamente se perderá en el código, creará errores y simplemente creará patrones anti que no son buenos para usted.
la pirámide de la perdición todavía funciona


Reducir el infierno de la devolución de llamada con funciones con nombre

JavaScript hace que sea fácil dispararse a sí mismo en el pie si no tiene cuidado. Una de esas características del lenguaje que le ayuda a hacer esto son las funciones anónimas. Getify es conocido por sugerir que siempre nombre sus funciones y tiene razón. La depuración de funciones anónimas es casi imposible. En cualquier caso, modifiquemos nuestro código hasta ahora para usar funciones con nombre y veamos cómo eso ayuda a mejorar la legibilidad. Aquí refactorizamos el código para usar funciones con nombre. Es mejor, pero aún no tan bueno.


Cómo pueden ayudar las promesas de JavaScript

Las promesas contienen el resultado final de una operación asincrónica. Cuando se completa una operación asincrónica, puede generar un valor o un error. Los tres estados que puede mantener una promesa son Pendiente, Cumplida o Rechazada. A continuación, se muestra un ejemplo ficticio del uso de una promesa para realizar una solicitud de API.

Cuando la solicitud de la API fue exitosa (apiResponse = 1), todo está bien.
Resolver promesa

Cuando la solicitud de la API no se realizó correctamente (apiResponse = 0), el .catch de la cadena de promesa muestra un error.
rechazar la promesa

Con este conocimiento, ahora podemos reemplazar las funciones asincrónicas que reciben una devolución de llamada, con una promesa devuelta. Veamos cómo.


Promesas en lugar de devoluciones de llamada

En el código de ejemplo que mostramos para el infierno de devolución de llamada, tenemos la estructura piramidal de fatalidad. En otras palabras, tenemos ese problema profundamente anidado que es difícil de leer. Aquí, podemos modificar las funciones asincrónicas para devolver ahora una promesa. Dado que esas funciones asíncronas devuelven una promesa, podemos consumir esas promesas usando .then () y .catch () eliminando así la pirámide anidada del infierno de devolución de llamada. Tenga en cuenta que la pirámide de la fatalidad ahora está comentada y reescrita usando una cadena .then () justo debajo. También tenga en cuenta que las funciones asincrónicas de soporte ya no aceptan una devolución de llamada como parámetro, ya que ahora devuelven una Promesa. Con suerte, está claro que dentro de la promesa devuelta es donde va ahora el código asíncrono (leer una base de datos o realizar una solicitud de API).


Async Await Syntactic Sugar

Finalmente, puede considerar usar la solución más nueva para devolver la llamada al infierno, y sería async / awaitEl objetivo de async / await es ayudar a los desarrolladores de software a escribir código asincrónico como si fuera un código sincrónico o con un estilo de apariencia sincrónica. Para demostrarlo, aquí está el código para el enfoque basado en Promise y Async / Await. Tenga en cuenta que el enfoque Promise está comentado.

Parece que el código también funciona con el método async / await.
async espera en nodejs

Algunas cosas clave para entender aquí sobre async / await. Utiliza la palabra clave await cuando llama a una función que devuelve una promesa. Esto le permite asignar el resultado a una constante o variable tal como lo haría en una operación síncrona. Por ejemplo, el código se const user = await getUser(1);ve muy agradable y sincrónico, pero la palabra clave await nos da una indicación de que la función está devolviendo una promesa. Esto ahora facilita la capacidad de llamar a getBlogPosts(user.name)pasar el objeto de usuario que acabamos de obtener en la línea de código anterior. Siempre que vea la palabra clave await antes de una función, sabrá que está devolviendo una promesa. Sin embargo, lo mejor es que ahora puede escribir ese código en un estilo de aspecto más sincrónico. La otra conclusión es que, dado que está utilizandoawaitdentro de una función, debe usar la palabra clave async en esa función. Async y Await se construyen sobre Promises y son una forma de tener una sintaxis más agradable al igual que las Clases ES6 son una sintaxis más agradable para Prototipos y Funciones de Constructor. Si escribir código asincrónico hace que su cabeza dé vueltas, entonces tal vez Async / Await sea justo lo que necesita.


Devolución de llamada de Javascript vs Promesas vs Async Await Resumen

Cuando escribe código asincrónico, es fácil meterse en problemas, especialmente si ha estado escribiendo código sincrónico durante mucho tiempo. La verdad es que hacer uso de las devoluciones de llamada de una manera limpia y concisa es un desafío. Es posible que te encuentres en la pirámide del infierno de devolución de llamada más rápido de lo que puedes parpadear. Puedes luchar contra el infierno de llamadas con estos consejos.

  • Usar módulos
  • Usar administradores de flujo de control
  • Usar promesas
  • Utilice Async Await
  • Lea algunos tutoriales más como
    • Front End semanal
    • Tinus Wagner
    • Hackernoon
    • Académico
  • Vea un excelente tutorial de Traversy Media