W3docs

Callbacks en JavaScript

Los callbacks en JavaScript son esenciales para manejar operaciones asíncronas. Aprende qué son, la convención error-first y cómo evitar el callback hell.

Un callback es simplemente una función que se pasa a otra función como argumento, de modo que la función receptora pueda invocarla más adelante. Como las funciones son valores de primera clase en JavaScript — pueden almacenarse en variables, pasarse como argumentos y devolverse como resultados —, cualquier función puede aceptar otra función como parámetro. Esta idea por sí sola impulsa todo, desde métodos de array como map hasta temporizadores y solicitudes de red.

Este capítulo trata qué son los callbacks, la diferencia entre callbacks síncronos y asíncronos, la convención error-first, el problema del callback hell que generan, y cómo las Promesas y async/await lo resuelven.

Un Primer Callback

La función que se pasa es el callback; la función que la recibe y la invoca es la función de orden superior. Aquí un callback se ejecuta una vez que termina cierto trabajo:

javascript— editable

finishTask se pasa a completeTask y se invoca dentro de ella. Nota que se pasa el nombre de la función (finishTask) sin paréntesis — añadir () la llamaría inmediatamente y pasaría su valor de retorno en su lugar.

Callbacks Síncronos vs. Asíncronos

No todos los callbacks implican espera. Existen dos tipos distintos, y confundirlos es una fuente habitual de errores.

Callbacks síncronos

Un callback síncrono se ejecuta de inmediato, en orden, antes de que la función exterior retorne. Los métodos de array son el ejemplo clásico:

javascript— editable

Aquí transform se llama y termina para cada elemento antes de que map retorne. Los métodos integrados como Array.prototype.map, filter, forEach y sort aceptan callbacks síncronos.

Callbacks asíncronos

Un callback asíncrono se entrega a una operación que se completa más adelante — un temporizador, la lectura de un archivo o una solicitud de red. La función exterior retorna de inmediato, y el callback se dispara una vez que el resultado está listo. JavaScript programa estos a través del event loop, que encola los callbacks y los ejecuta cuando la pila de llamadas está vacía.

javascript— editable

Incluso con un retraso de 0 ms, el callback se ejecuta después del código síncrono circundante. Esa es la característica definitoria de un callback asíncrono: no puede devolver un valor de la manera habitual, así que la única forma de usar el resultado es colocar el código de continuación dentro del callback. Para entender exactamente cuándo se ejecutan, consulta JavaScript: Event Loop.

La Convención Error-First

Los callbacks asíncronos no pueden lanzar excepciones con throw al código que inició la operación — en el momento en que se ejecutan, ese código ya ha retornado hace tiempo. La comunidad adoptó una convención: pasar el error como primer argumento y el resultado como segundo. El callback siempre comprueba el error primero.

javascript— editable

Cuando todo tiene éxito, el slot del error es null. Esta firma (err, result) es el estándar en las APIs de Node.js (fs.readFile, dns.lookup y muchas más).

Callback Hell: La Pirámide del Caos

Los callbacks funcionan bien para una sola operación. El problema comienza cuando un paso asíncrono depende del resultado del anterior. Cada paso se anida dentro del último, y la indentación avanza hacia la derecha — la llamada pirámide del caos:

javascript— editable

Con dos pasos aún resulta legible. Añade un tercero y un cuarto — y repite la comprobación if (err) en cada nivel — y el código se vuelve difícil de seguir, difícil de manejar en cuanto a errores y difícil de modificar. Esto es el callback hell, y es la razón principal por la que se introdujeron las Promesas.

Buenas Prácticas al Usar Callbacks

Aunque los callbacks son poderosos, usarlos de forma excesiva o incorrecta puede llevar al "callback hell", donde el código se anida demasiado profundamente y resulta difícil de leer y mantener. Estas son algunas buenas prácticas para mantener el código limpio:

  1. Modulariza tu código: Divide tus funciones callback en funciones más pequeñas y reutilizables. Este enfoque no solo mejora la legibilidad, sino también el mantenimiento del código.
  2. Maneja los errores con elegancia: Gestiona siempre los errores en tus callbacks. Esta práctica evita fallos y comportamientos no deseados en entornos de producción.
  3. Evita el anidamiento profundo: Intenta aplanar tus estructuras de callbacks tanto como sea posible. Herramientas como async/await o las Promesas pueden ayudar a gestionar las operaciones asíncronas de forma más limpia.
  4. Ten cuidado con los closures en bucles: Al definir callbacks dentro de bucles, usa let o const para las variables del bucle y así evitar errores relacionados con closures donde todos los callbacks capturan el valor final del bucle.

Más Allá de los Callbacks: Promesas y Async/Await

Aunque los callbacks son una parte fundamental de JavaScript, el JavaScript moderno ofrece formas más abstractas de manejar el código asíncrono, como las Promesas y async/await.

Uso de Promesas

Una Promesa representa un valor que puede estar disponible ahora, en el futuro o nunca. En lugar de anidar, los pasos dependientes se encadenan uno tras otro, lo que aplana la pirámide y centraliza el manejo de errores en un único .catch. Comienza con JavaScript: Promises, luego observa cómo se conectan los pasos en JavaScript: Promises Chaining.

Si tienes una función antigua basada en callbacks (como los ejemplos de divide o getUser anteriores), puedes envolverla para que devuelva una Promesa — una técnica llamada promisificación. Consulta JavaScript: Promisification.

Async/Await: Un Enfoque Más Limpio

La sintaxis async/await permite escribir código asíncrono que se lee como código síncrono. Está construida sobre las Promesas y resulta más intuitiva que los patrones de callback tradicionales. Lee JavaScript: Async/Await para ver cómo puedes usar async/await en lugar de callbacks.

Conclusión

Comprender y utilizar los callbacks de forma efectiva es fundamental para los desarrolladores de JavaScript. Siguiendo las buenas prácticas y usando características modernas como las Promesas y async/await, puedes escribir código más limpio y fácil de mantener. Domina estos conceptos para mejorar tus habilidades de programación en JavaScript y construir aplicaciones más eficientes.

Práctica

Práctica
¿Qué es una función callback en JavaScript y cuándo se ejecuta?
¿Qué es una función callback en JavaScript y cuándo se ejecuta?
Was this page helpful?