Este artículo da una breve introducción al concepto y uso de las funciones callback en el lenguaje de programación Javascript.

Las Funciones son Objetos

Lo primero que tenemos que saber es que en Javascript, las funciones son objetos de primera clase. Como tales, podemos trabajar con ellos de la misma forma que trabajamos con otros objetos, como asignarlos a variables y pasarlos como argumentos a otras funciones. Esto es importante, porque esta última técnica nos permite ampliar la funcionalidad de nuestras aplicaciones.

Funciones Callback

Una función callback es aquella que es pasada como argumento a otra función para que sea "llamada de nuevo" (call back) en un momento posterior. Una función que acepta otras funciones como argumentos es llamada función de orden-superior (High-Order), y contiene la lógica para determinar cuándo se ejecuta la función callback. Es la combinación de estas dos la que nos permite ampliar nuestra funcionalidad.

Para ilustrar las funciones callback, iniciemos con un ejemplo simple:

function crearCita(cita, callback){ 
  var miCita = "Como yo siempre digo, " + cita;
  callback(miCita); // 2
}

function logCita(cita){
  console.log(cita);
}

crearCita("come tus vegetales!", logCita); // 1

// Resultado en la consola: 
// Como yo siempre digo, come tus vegetales!

En el ejemplo anterior, crearCita es la función de orden-superior, la cual acepta dos argumentos, el segundo es el callback. La función logCita se está pasando como nuestra función callback. Cuando ejecutamos la función  crearCita  (1), observa que no estamos agregando paréntesis a logCita al pasarla como argumento. Esto se debe a que no queremos ejecutar nuestra función callback de inmediato, simplemente queremos pasar la definición de la función a la función de orden-superior para que pueda ejecutarse más tarde.

Además, debemos asegurarnos que si la función callback que pasamos espera argumentos, debemos proporcionarlos al ejecutarla (2). En el ejemplo anterior, eso sería la declaración callback(miCita); ya que sabemos que logCita  espera que se pase una cita.

Además, podemos pasar funciones anónimas como callbacks. La siguiente llamada a crearCita  tendrá el mismo resultado que el ejemplo anterior:

crearCita("come tus vegetales!", function(cita){ 
  console.log(cita); 
});

Por cierto, tu no estás obligado a usar la palabra "callback" como el nombre de tu argumento, Javascript solo necesita saber que es el nombre correcto del argumento. Según el ejemplo anterior, la siguiente función se comportará exactamente de la misma manera.

function crearCita(cita, funcionParaLlamar) { 
  var miCita = "como siempre digo, " + cita;
  funcionParaLlamar(miCita);
}

¿Por qué usar funciones Callback?

La mayoría del tiempo estamos creando programas y aplicaciones que operan en una forma sincrónica. En otras palabras, algunos de nuestra operaciones comienzan solo después de que se hayan completado las anteriores. Usualmente, cuando solicitamos datos desde otras fuentes como una API externa, no siempre sabemos cuando nuestros datos serán devueltos. En estos casos queremos esperar la respuesta, pero no queremos que toda nuestra aplicación se detenga mientras se recuperan los datos. Estas son situaciones dónde las funciones callback resultan útiles.

Veamos un ejemplo que simula una solicitud a un servidor:

function solicitudServidor(consulta, callback){
  setTimeout(function(){
    var respuesta = consulta + "lleno!";
    callback(respuesta);
  },5000);
}

function obtenerResultados(resultados){
  console.log("Respuesta del servidor: " + resultados);
}

solicitudServidor("El vaso está medio  ", obtenerResultados);

//Resultado en la consola luego de 5 segundos:
// El vaso está medio lleno!

En el ejemplo anterior hacemos una solicitud simulada al servidor. Después de que pasen cinco segundos, la respuesta es modificada y luego nuestra función callback   obtenerResultados se ejecuta. Para ver esto en acción, puedes copiar / pegar el código anterior en las herramientas de desarrollador de tu navegador y ejecutarlo.

Además, si ya estás familiarizado con la función setTimeout, entonces has estado usando funciones callback todo el tiempo. El argumento de función anónima pasado a la llamada de la función setTimeout en el ejemplo anterior ¡también es un callback! Entonces la función callback del ejemplo es en realidad ejecutada por otro callback. Ten cuidado de no anidar demasiadas funciones callback si puedes evitarlo, ya que esto puede llevar a algo llamado "infierno de callbacks". Como su nombre lo indica, no es un placer lidiar con él.

Traducido del artículo - What is a Callback Function in JavaScript?