¿Qué son los callbacks?

Funciones callback o retrollamadas


Los callbacks (a veces denominados funciones de retrollamada o funciones callback) no son más que un tipo de funciones que se pasan por parámetro a otras funciones. El objetivo de esto es tener una forma reutilizable de escribir funciones, que además entra bastante en consonancia con el concepto de asincronía de Javascript.

Ten en cuenta que actualmente, controlar la asincronía únicamente mediante callbacks puede ser una práctica poco recomendable. Es preferible utilizar promesas, que generalmente es lo más cómodo.

¿Qué es un callback?

Como hemos dicho, las funciones callback no son más que un tipo de funciones que se pasan por parámetro a otras funciones. Además, los parámetros de esos callbacks toman un valor especial en el interior de la función.

Pero para entenderlo bien, veamos un ejemplo. Imaginemos el siguiente bucle for tradicional para recorrer un :

const letters = ["A", "B", "C"];

for (let pos = 0; pos < letters.length; pos++) {
  const letter = letters[pos];
  console.log(`pos=${pos} letter=${letter}`);
}

En la variable pos tenemos la posición del array que estamos recorriendo. Este valor irá desde 0 hasta 2, mientras que en letter guardamos letters[pos], es decir, la posición en el array, obteniendo el elemento, es decir, desde A hasta C:

pos=0 letter=A
pos=1 letter=B
pos=2 letter=C

Ahora veamos, como podemos hacer este mismo bucle utilizando el método forEach() del al cuál le pasamos una función callback. La función callback es action() y ten en cuenta que los parámetros element e index son parámetros «especiales» al ser una función callback:

const letters = ["A", "B", "C"];

function action(element, index) {
  console.log(`pos=${index} letter=${element}`);
}

// Por cada item del array, ejecuta action()
letters.forEach(action);

Esto se suele reescribir habitualmente de la siguiente forma:

letters.forEach((element, index) => {
  console.log(`pos=${index} letter=${element}`);
});

Lo importante de este ejemplo es que se vea que la función callback que le hemos pasado por parámetro a forEach() se va a ejecutar por cada uno de los elementos del array, y en cada iteración de dicha función callback, los parámetros element e index van a tener un valor especial:

  • element es el elemento del array
  • index es el índice (posición) del array

Callbacks en Javascript

Una vez entendido esto, vamos a profundizar un poco con las funciones callbacks utilizadas para realizar tareas asíncronas. Probablemente, el caso más fácil de entender es utilizar un temporizador mediante la función setTimeout(callback, time).

Dicha función nos exige dos parámetros:

  • La función callback a ejecutar
  • El tiempo time que esperará antes de ejecutarse

Observa el siguiente ejemplo. Simplemente, le decimos a setTimeout() que ejecute la función callback que le hemos pasado por primer parámetro cuando transcurran 2000 milisegundos (es decir, 2 segundos):

function action() {
  console.log("He ejecutado la función");
}

setTimeout(action, 2000);

Utilizando arrow functions y escribiendo la función directamente, se puede simplificar el callback y hacerlo más fácil de escribir:

setTimeout(() => console.log("He ejecutado la función"), 2000);

En cualquiera de los casos, lo importante es darse cuenta que estamos usando una función callback para pasársela a setTimeout(), que es otra función. En este caso, se trata de «programar» un suceso que ocurrirá en un momento concreto del futuro, pero muchas veces desconociendo cuando se producirá exactamente (o incluso si se llegará a producir).

Orden de ejecución

Si probamos el siguiente código en una consola del navegador, comprobarás que el segundo console.log() se ejecutará antes que el primer console.log() que está dentro del setTimeout(), mostrando primero Código síncrono y luego Código asíncrono:

setTimeout(() => {
  console.log("Código asíncrono.");
}, 2000);

console.log("Código síncrono.");

El último console.log() del código se ejecuta primero (forma parte del flujo principal de ejecución del programa). El setTimeout() que figura en una línea anterior, aunque se ejecuta antes, pone en espera a la función callback, que se ejecutará cuando se cumpla una cierta condición (en este caso, cuando transcurran 2 segundos desde ese momento).

Esto puede llegar a sorprender a desarrolladores que llegan de otros lenguajes considerados bloqueantes; Javascript sin embargo se considera un lenguaje que puede escribir código asíncrono y no bloqueante. ¿Qué significa esto? Al ejecutar la línea del setTimeout(), el programa no se queda bloqueado esperando a que terminen los 2 segundos y se ejecute la función callback, sino que continúa con el flujo general del programa para volver más adelante cuando sea necesario a ejecutar la función callback, aprovechando así mejor el tiempo y realizando tareas de forma asíncrona.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev