¿Cómo explicar las devoluciones de llamada en inglés simple? ¿Cómo son diferentes de llamar a una función de otra función?

342

¿Cómo explicar las devoluciones de llamada en inglés simple? ¿En qué se diferencian de llamar a una función de otra función tomando algún contexto de la función de llamada? ¿Cómo se puede explicar su poder a un programador novato?

Yahoo-Me
fuente
1
Creo que su nombre científico es estilo de paso continuo. Puedes buscar esto en wiki.
ming_codes
1
Hay algunas buenas respuestas a una misma pregunta en Quora también
DBR
La mejor explicación de devolución de llamada que he encontrado youtube.com/watch?v=xHneyv38Jro
Sameer Sinha

Respuestas:

114

A menudo, una aplicación necesita ejecutar diferentes funciones en función de su contexto / estado. Para esto, usamos una variable donde almacenaríamos la información sobre la función que se llamará. Según su necesidad, la aplicación configurará esta variable con la información sobre la función que se llamará y llamará a la función utilizando la misma variable.

En javascript, el ejemplo está debajo. Aquí usamos el argumento del método como una variable donde almacenamos información sobre la función.

function processArray(arr, callback) {
    var resultArr = new Array(); 
    for (var i = arr.length-1; i >= 0; i--)
        resultArr[i] = callback(arr[i]);
    return resultArr;
}

var arr = [1, 2, 3, 4];
var arrReturned = processArray(arr, function(arg) {return arg * -1;});
// arrReturned would be [-1, -2, -3, -4]
Niraj Nawanit
fuente
18
Si bien esto es técnicamente una devolución de llamada, la explicación dada parece indiferente de un puntero de función general. Sería útil incluir alguna justificación de por qué podría usarse una devolución de llamada.
Eric
44
No entiendo esta respuesta. ¿Puede ser más sobre explicar que el código?
Abhishek Singh
por qué no podemos hacer lo que hacemos en la función de devolución de llamada (the function(arg)) en la processArray(arr,callback)función
Abhi
1
@JoSmo tienes razón en parte. Pase una variable + función de devolución de llamada como parámetros tomando el resultado creado con la variable por la función original y páselo en la función de devolución de llamada para su posterior procesamiento. ejemplo: func1 (a, callback_func) {v = a + 1} y hay una función de devolución de llamada predefinida: callback_func (v) {return v + 1;} esto aumentará a en 2, por lo que si pasa el argumento del número entero 4 en parámetro "a", callback_funct devolverá 6 como resultado. Lea esta mejor fuente de callbackhell.com que encontré.
Estiércol
Esta respuesta no es clara. ¡Podría ser más simple y articulado!
Arjun Kalidas
545

Voy a tratar de mantener esto muy simple. Una "devolución de llamada" es cualquier función que es llamada por otra función que toma la primera función como parámetro. Muchas veces, una "devolución de llamada" es una función que se llama cuando sucede algo . Ese algo se puede llamar un "evento" en lenguaje de programador.

Imagine este escenario: está esperando un paquete en un par de días. El paquete es un regalo para tu vecino. Por lo tanto, una vez que obtenga el paquete, desea que lo traigan a los vecinos. Está fuera de la ciudad, por lo que deja instrucciones para su cónyuge.

Podrías decirles que obtengan el paquete y se lo lleven a los vecinos. Si su cónyuge fuera tan estúpido como una computadora, se sentarían en la puerta y esperarían el paquete hasta que llegara (NO HACER NADA MÁS) y luego, una vez que llegara, lo llevarían a los vecinos. Pero hay una mejor manera. Dígale a su cónyuge que UNA VEZ que reciben el paquete, deben llevarlo a los vecinos. Luego, pueden continuar con la vida normalmente HASTA que reciban el paquete.

En nuestro ejemplo, la recepción del paquete es el "evento" y la entrega a los vecinos es la "devolución de llamada". Su cónyuge "ejecuta" sus instrucciones para llevar el paquete solo cuando llegue el paquete. ¡Mucho mejor!

Este tipo de pensamiento es obvio en la vida diaria, pero las computadoras no tienen el mismo tipo de sentido común. Considere cómo los programadores normalmente escriben en un archivo:

fileObject = open(file)
# now that we have WAITED for the file to open, we can write to it
fileObject.write("We are writing to the file.")
# now we can continue doing the other, totally unrelated things our program does

Aquí, ESPERAMOS que se abra el archivo, antes de escribirlo. ¡Esto "bloquea" el flujo de ejecución, y nuestro programa no puede hacer ninguna de las otras cosas que podría necesitar hacer! ¿Qué pasaría si pudiéramos hacer esto en su lugar?

# we pass writeToFile (A CALLBACK FUNCTION!) to the open function
fileObject = open(file, writeToFile)
# execution continues flowing -- we don't wait for the file to be opened
# ONCE the file is opened we write to it, but while we wait WE CAN DO OTHER THINGS!

Resulta que hacemos esto con algunos lenguajes y marcos. ¡Es genial! Echa un vistazo a Node.js para obtener una práctica real con este tipo de pensamiento.

Josh Imhoff
fuente
66
Esto es correcto, pero no cubre todos los casos de uso comunes para devoluciones de llamada. A menudo usa devoluciones de llamada cuando necesita llamar a una función con argumentos que se procesarían en el proceso de otra función. Por ejemplo, en PHP, array_filter () y array_map () toman devoluciones de llamada para ser llamadas en un bucle.
Haralan Dobrev
2
¿Es apropiado el ejemplo de archivo de escritura? Parece hacer suposiciones sobre cómo openfunciona. Es openposible que se bloquee internamente mientras espera que el sistema operativo haga su magia negra, sobre la cual se ejecuta la devolución de llamada. No hay diferencia en el resultado en tal caso.
Kenneth K.
23
Buena explicación, pero estoy confundiendo un poco. ¿La devolución de llamada es multiproceso?
Premraj
1
Gran ejemplo! Estaba buscando un inglés sencillo en todo el lugar y este es el primero que he encontrado hasta ahora :)
ChristoKiwi
1
¿Qué hace que la función de apertura en su ejemplo no bloquee? abrir aún puede bloquear el flujo de ejecución ..
Koray Tugay
82

¿Cómo explicar las devoluciones de llamada en inglés simple?

En inglés simple, una función de devolución de llamada es como un Trabajador que "devuelve la llamada" a su Gerente cuando ha completado una Tarea .

¿En qué se diferencian de llamar a una función de otra función tomando algún contexto de la función de llamada?

Es cierto que está llamando a una función desde otra función, pero la clave es que la devolución de llamada se trata como un Objeto, por lo que puede cambiar qué Función llamar en función del estado del sistema (como el Patrón de Diseño de Estrategia).

¿Cómo se puede explicar su poder a un programador novato?

El poder de las devoluciones de llamada se puede ver fácilmente en los sitios web de estilo AJAX que necesitan extraer datos de un servidor. La descarga de los nuevos datos puede llevar algún tiempo. Sin devoluciones de llamada, toda su interfaz de usuario se "congelaría" mientras descarga los nuevos datos, o necesitaría actualizar toda la página en lugar de solo una parte de ella. Con una devolución de llamada, puede insertar una imagen de "cargando ahora" y reemplazarla con los nuevos datos una vez cargada.

Algún código sin devolución de llamada:

function grabAndFreeze() {
    showNowLoading(true);
    var jsondata = getData('http://yourserver.com/data/messages.json');
    /* User Interface 'freezes' while getting data */
    processData(jsondata);
    showNowLoading(false);
    do_other_stuff(); // not called until data fully downloaded
}

function processData(jsondata) { // do something with the data
   var count = jsondata.results ? jsondata.results.length : 0;
   $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
   $('#results_messages').html(jsondata.results || '(no new messages)');
}

Con devolución de llamada:

Aquí hay un ejemplo con una devolución de llamada, usando getJSON de jQuery :

function processDataCB(jsondata) { // callback: update UI with results
   showNowLoading(false);
   var count = jsondata.results ? jsondata.results.length : 0;
   $('#counter_messages').text(['Fetched', count, 'new items'].join(' '));
   $('#results_messages').html(jsondata.results || '(no new messages)');
}

function grabAndGo() { // and don't freeze
    showNowLoading(true);
    $('#results_messages').html(now_loading_image);
    $.getJSON("http://yourserver.com/data/messages.json", processDataCB);
    /* Call processDataCB when data is downloaded, no frozen User Interface! */
    do_other_stuff(); // called immediately
}

Con cierre:

A menudo, la devolución de llamada necesita acceder statedesde la función de llamada usando a closure, que es como si el Trabajador necesitara obtener información del Administrador antes de que pueda completar su Tarea . Para crear closure, puede alinear la función para que vea los datos en el contexto de llamada:

/* Grab messages, chat users, etc by changing dtable. Run callback cb when done.*/
function grab(dtable, cb) { 
    if (null == dtable) { dtable = "messages"; }
    var uiElem = "_" + dtable;
    showNowLoading(true, dtable);
    $('#results' + uiElem).html(now_loading_image);
    $.getJSON("http://yourserver.com/user/"+dtable+".json", cb || function (jsondata) {
       // Using a closure: can "see" dtable argument and uiElem variables above.
       var count = jsondata.results ? jsondata.results.length : 0, 
           counterMsg = ['Fetched', count, 'new', dtable].join(' '),
           // no new chatters/messages/etc
           defaultResultsMsg = ['(no new ', dtable, ')'].join(''); 
       showNowLoading(false, dtable);
       $('#counter' + uiElem).text(counterMsg);
       $('#results'+ uiElem).html(jsondata.results || defaultResultsMsg);
    });
    /* User Interface calls cb when data is downloaded */

    do_other_stuff(); // called immediately
}

Uso:

// update results_chatters when chatters.json data is downloaded:
grab("chatters"); 
// update results_messages when messages.json data is downloaded
grab("messages"); 
// call myCallback(jsondata) when "history.json" data is loaded:
grab("history", myCallback); 

Cierre

Por último, aquí hay una definición closurede Douglas Crockford :

Las funciones se pueden definir dentro de otras funciones. La función interna tiene acceso a los vars y parámetros de la función externa. Si sobrevive una referencia a una función interna (por ejemplo, como una función de devolución de llamada), los vars de la función externa también sobreviven.

Ver también:

usuario508994
fuente
12
+1. El primer párrafo es golpear el dinero . Sin embargo, el resto entra en la jerga informática bastante rápido.
TarkaDaal
41

Me sorprende ver a tantas personas inteligentes que no hacen hincapié en la realidad que la palabra "devolución de llamada" se ha utilizado de dos maneras inconsistentes.

Ambas formas implican la personalización de una función pasando funcionalidad adicional (una definición de función, anónima o con nombre) a una función existente. es decir.

customizableFunc(customFunctionality)

Si la funcionalidad personalizada simplemente se conecta al bloque de código, usted ha personalizado la función, así.

    customizableFucn(customFunctionality) {
      var data = doSomthing();
      customFunctionality(data);
      ...
    }

Aunque este tipo de funcionalidad inyectada a menudo se denomina "devolución de llamada", no tiene nada de contingente. Un ejemplo muy obvio es el método forEach en el que se proporciona una función personalizada como argumento que se aplicará a cada elemento de una matriz para modificar la matriz.

Pero esto es fundamentalmente distinto del uso de funciones de "devolución de llamada" para la programación asincrónica , como en AJAX o node.js o simplemente en la asignación de funcionalidad a eventos de interacción del usuario (como los clics del mouse). En este caso, la idea es esperar a que ocurra un evento contingente antes de ejecutar la funcionalidad personalizada. Esto es obvio en el caso de la interacción del usuario, pero también es importante en los procesos de E / S (entrada / salida) que pueden llevar tiempo, como leer archivos del disco. Aquí es donde el término "devolución de llamada" tiene el sentido más obvio. Una vez que se inicia un proceso de E / S (como pedir que se lea un archivo desde el disco o un servidor para devolver datos de una solicitud http), se produce un asíncronoel programa no espera a que termine. Puede continuar con las tareas que se programan a continuación, y solo responder con la funcionalidad personalizada después de que se le haya notificado que el archivo de lectura o la solicitud http se ha completado (o que falló) y que los datos están disponibles para la funcionalidad personalizada. Es como llamar a una empresa por teléfono y dejar su número de "devolución de llamada", para que puedan llamarlo cuando alguien esté disponible para responderle. Eso es mejor que esperar en la línea por quién sabe cuánto tiempo y no poder atender otros asuntos.

El uso asincrónico implica de manera inherente algunos medios de escuchar el evento deseado (por ejemplo, la finalización del proceso de E / S) para que, cuando ocurra (y solo cuando ocurra), se ejecute la funcionalidad personalizada de "devolución de llamada". En el ejemplo obvio de AJAX, cuando los datos realmente llegan del servidor, la función de "devolución de llamada" se activa para usar esos datos para modificar el DOM y, por lo tanto, volver a dibujar la ventana del navegador en esa medida.

Recordar. Algunas personas usan la palabra "devolución de llamada" para referirse a cualquier tipo de funcionalidad personalizada que se puede inyectar en una función existente como argumento. Pero, al menos para mí, el uso más apropiado de la palabra es donde la función de "devolución de llamada" inyectada se usa de forma asíncrona, para ejecutarse solo cuando se produce un evento del que está esperando ser notificado.

Robert Polevoi
fuente
Entonces, cuando la función devuelve la llamada, ¿a dónde regresa el proceso? Por ejemplo, si hay cuatro líneas de código; 1.fileObject = open (archivo, writeToFile); 2. hacer algo1 (); 3. doSomething2 (); 4. doSomething3 ().
MagicLAMP
La línea 1 se ejecuta, pero en lugar de esperar a que se abra el archivo, pasa a la línea 2, luego a 3. En ese punto, el archivo se abre y (una vez que la línea 3 ha finalizado cualquier operación de semáforo) devuelve la llamada al contador del programa para decir " pasar control a writeToFile ", que hace cosas, y cuando se termina, pasa el control al punto en el que se produjo el INT en la línea 3, o en la línea 4 si la línea 3 llega a su fin.
MagicLAMP
1
Esta es una explicación muy articulada de otro punto importante: por ejemplo, la diferencia entre la función transmitida como un argumento a Array.prototype.forEach()y la función transmitida como un argumento a setTimeout(), y son caballos de diferentes colores en la forma en que razona sobre su programa .
mikermcneil
26

En términos no programadores, una devolución de llamada es un espacio en blanco en un programa.

Un elemento común en muchos formularios en papel es "Persona a quien llamar en caso de emergencia". Hay una línea en blanco allí. Escribe el nombre y el número de teléfono de alguien. Si ocurre una emergencia, entonces se llama a esa persona.

  • Todos obtienen el mismo formulario en blanco, pero
  • Todos pueden escribir un número de contacto de emergencia diferente.

Esta es la clave. No cambia el formulario (el código, generalmente el de otra persona). Sin embargo, puede completar los datos faltantes ( su número).

Ejemplo 1:

Las devoluciones de llamada se utilizan como métodos personalizados, posiblemente para agregar / cambiar el comportamiento de un programa. Por ejemplo, tome un código C que realice una función, pero no sepa cómo imprimir la salida. Todo lo que puede hacer es hacer una cadena. Cuando intenta averiguar qué hacer con la cadena, ve una línea en blanco. ¡Pero el programador le dio el espacio en blanco para escribir su devolución de llamada!

En este ejemplo, no usa un lápiz para rellenar un espacio en blanco en una hoja de papel, usa la función set_print_callback(the_callback).

  • La variable en blanco en el módulo / código es la línea en blanco,
  • set_print_callback es el lapiz
  • y the_callbackes su información que está completando.

Ahora ha completado esta línea en blanco en el programa. Siempre que necesite imprimir la salida, verá esa línea en blanco y seguirá las instrucciones allí (es decir, llame a la función que puso allí). Prácticamente, esto permite la posibilidad de imprimir en la pantalla, en un archivo de registro, en una impresora, a través de una conexión de red, o cualquier combinación de las mismas. Has completado el espacio en blanco con lo que quieres hacer.

Ejemplo 2

Cuando le dicen que necesita llamar a un número de emergencia, va y lee lo que está escrito en el formulario en papel, y luego llama al número que leyó. Si esa línea está en blanco no se hará nada.

La programación gui funciona de la misma manera. Cuando se hace clic en un botón, el programa necesita descubrir qué hacer a continuación. Se va y busca la devolución de llamada. Esta devolución de llamada se encuentra en un espacio en blanco con la etiqueta "Esto es lo que debe hacer cuando se hace clic en Button1"

La mayoría de los IDEs completarán automáticamente el espacio en blanco por usted (escriba el método básico) cuando se lo pida (por ejemplo button1_clicked). Sin embargo, ese espacio en blanco puede tener cualquier método que quieras, por favor . Puede llamar al método run_computationso butter_the_biscuitssiempre que ponga el nombre de la devolución de llamada en el espacio en blanco adecuado. Puede poner "555-555-1212" en el número de emergencia en blanco. No tiene mucho sentido, pero está permitido.


Nota final: ¿Esa línea en blanco que está completando con la devolución de llamada? Se puede borrar y reescribir a voluntad. (si debería o no es otra pregunta, pero eso es parte de su poder)

JoeyG
fuente
22

Siempre es mejor comenzar con un ejemplo :).

Supongamos que tiene dos módulos A y B.

Desea que se le notifique al módulo A cuando se produce algún evento / condición en el módulo B. Sin embargo, el módulo B no tiene idea de su módulo A. Todo lo que sabe es una dirección a una función particular (del módulo A) a través de un puntero de función que es proporcionado por el módulo A.

Entonces, todo lo que B tiene que hacer ahora, es "devolución de llamada" en el módulo A cuando ocurre un evento / condición particular usando el puntero de función. A puede hacer más procesamiento dentro de la función de devolución de llamada.

*) Una clara ventaja aquí es que está abstrayendo todo lo relacionado con el módulo A del módulo B. El módulo B no tiene que preocuparse por quién / qué es el módulo A.

Gargi Srinivas
fuente
Entonces, los parámetros para la función en A se proporcionan en el módulo B, ¿es correcto?
U.Savas
21

Imagina que necesitas una función que devuelva 10 al cuadrado para escribir una función:

function tenSquared() {return 10*10;}

Luego necesitas 9 al cuadrado para escribir otra función:

function nineSquared() {return 9*9;}

Eventualmente, reemplazará todo esto con una función genérica:

function square(x) {return x*x;}

Se aplica exactamente el mismo pensamiento para las devoluciones de llamada. Tiene una función que hace algo y, cuando termina, llama a doA:

function computeA(){
    ...
    doA(result);
}

Más tarde, desea exactamente la misma función para llamar a doB; en su lugar, podría duplicar toda la función:

function computeB(){
    ...
    doB(result);
}

O podría pasar una función de devolución de llamada como variable y solo tener que tener la función una vez:

function compute(callback){
    ...
    callback(result);
}

Entonces solo tiene que llamar a compute (doA) y compute (doB).

Más allá de simplificar el código, permite que el código asíncrono le permita saber que se ha completado llamando a su función arbitraria al finalizar, similar a cuando llama a alguien por teléfono y deja un número de devolución de llamada.

Brian Nickel
fuente
Entonces estás pasando la función como parámetro. ¿Todo lenguaje de programación permite pasar la función como parámetro? En caso negativo, puede mostrar un ejemplo sobre cómo implementar la función de devolución de llamada en ese idioma.
Quazi Irfan
21

Johny, el programador, necesita una engrapadora, por lo que va al departamento de suministros de oficina y solicita una, luego de completar el formulario de solicitud, puede quedarse allí y esperar a que el empleado busque en la bodega la grapadora (como una llamada de función de bloqueo ) o ir a hacer otra cosa mientras tanto.

Como esto suele llevar tiempo, johny pone una nota junto con el formulario de solicitud pidiéndoles que lo llamen cuando la grapadora esté lista para que la recojan, por lo tanto, puede ir a hacer otra cosa como tomar una siesta en su escritorio.

tovmeod
fuente
1
Esto parece un poco más parecido a las promesas que a las devoluciones de llamada: blog.jcoglan.com/2013/03/30/…
Thomas
2
Las promesas son solo azúcar sintáctica en torno a las devoluciones de llamada.
Deven Phillips el
11

Te sientes mal, así que vas al médico. Él te examina y determina que necesitas algún medicamento. Prescribe algunos medicamentos y llama la receta a su farmacia local. Ve a casa. Más tarde, su farmacia llama para decirle que su receta está lista. Ve y recógelo.

efigie
fuente
Muy buena analogía. ¿Podría expandirse un poco más, tal vez con algunos ejemplos relacionados con la programación (simple)?
a20
10

Hay dos puntos para explicar, uno es cómo funciona una devolución de llamada (pasar una función que se puede llamar sin ningún conocimiento de su contexto), y el otro para qué se utiliza (manejar eventos de forma asincrónica).

La analogía de esperar a que llegue un paquete que ha sido utilizado por otras respuestas es buena para explicar ambas. En un programa de computadora, le dirías a la computadora que espere un paquete. Por lo general, ahora se sentaría allí y esperaría (y no haría nada más) hasta que llegue el paquete, posiblemente indefinidamente si nunca llega. Para los humanos, esto suena tonto, pero sin más medidas, esto es totalmente natural para una computadora.

Ahora la devolución de llamada sería el timbre de tu puerta principal. Proporcionas al servicio de paquetería una forma de notificarte sobre la llegada de la parcela sin que tengan que saber dónde (incluso si) estás en la casa o cómo funciona el timbre. (Por ejemplo, algunas "campanas" en realidad envían una llamada telefónica). Debido a que proporcionó una "función de devolución de llamada" que se puede "llamar" en cualquier momento, fuera de contexto, ahora puede dejar de sentarse en el porche y "manejar el evento "(de la llegada del paquete) cuando sea el momento.

Hanno Fietz
fuente
Esto es simple inglés.
Jeb50
¡Esta parece ser la mejor explicación!
Vishal Sharma
6

Imagina que un amigo está saliendo de tu casa y le dices "Llámame cuando llegues a casa para que sepa que llegaste a salvo"; eso es (literalmente) una devolución de llamada . Eso es lo que es una función de devolución de llamada, independientemente del idioma. Desea que algún procedimiento le devuelva el control cuando haya completado alguna tarea, por lo que le da una función para que le devuelva la llamada.

En Python, por ejemplo,

grabDBValue( (lambda x: passValueToGUIWindow(x) ))

grabDBValuepodría escribirse solo para obtener un valor de una base de datos y luego permitirle especificar qué hacer realmente con el valor, para que acepte una función. No sabe cuándo o si grabDBValuevolverá, pero si / cuándo lo hace, sabe lo que quiere que haga. Aquí, paso una función anónima (o lambda ) que envía el valor a una ventana GUI. Podría cambiar fácilmente el comportamiento del programa haciendo esto:

grabDBValue( (lambda x: passToLogger(x) ))

Las devoluciones de llamada funcionan bien en lenguajes donde las funciones son valores de primera clase , al igual que los enteros habituales, cadenas de caracteres, booleanos, etc. En C, puede "pasar" una función pasando un puntero y la persona que llama puede usar eso; en Java, la persona que llama solicitará una clase estática de cierto tipo con un nombre de método determinado ya que no hay funciones ("métodos" realmente) fuera de las clases; y en la mayoría de los otros lenguajes dinámicos puedes pasar una función con una sintaxis simple.

Protip:

En idiomas con alcance léxico (como Scheme o Perl), puede hacer un truco como este:

my $var = 2;
my $val = someCallerBackFunction(sub callback { return $var * 3; });
# Perlistas note: I know the sub doesn't need a name, this is for illustration

$valen este caso será 6porque la devolución de llamada tiene acceso a las variables declaradas en el entorno léxico donde se definió. El alcance léxico y las devoluciones de llamadas anónimas son una combinación poderosa que garantiza un mayor estudio para el programador novato.

Gatlin
fuente
1
+1. De hecho, me gusta bastante esta respuesta. La explicación de lo que una devolución de llamada es , es simple y concisa.
TarkaDaal
6

Tienes un código que quieres ejecutar. Normalmente, cuando lo llama, está esperando que termine antes de continuar (lo que puede hacer que su aplicación se vuelva gris / produzca un tiempo de giro para un cursor).

Un método alternativo es ejecutar este código en paralelo y continuar con su propio trabajo. Pero, ¿qué pasa si su código original necesita hacer cosas diferentes dependiendo de la respuesta del código que llamó? Bueno, en ese caso, puede pasar el nombre / ubicación del código al que desea que llame cuando esté listo. Esta es una "devolución de llamada".

Código normal: Solicitar información-> Información de proceso-> Manejar los resultados del procesamiento-> Continuar haciendo otras cosas.

Con devoluciones de llamada: Solicite información-> Información de proceso-> Continúe haciendo otras cosas. Y en algún momento posterior-> Tratar con los resultados del procesamiento.

Andrew Ducker
fuente
6

Sin devolución de llamada ni otros recursos de programación especiales (como subprocesos y otros), un programa es exactamente una secuencia de instrucciones que se ejecutan secuencialmente una tras otra , e incluso con un tipo de "comportamiento dinámico" determinado por ciertas condiciones, todos los escenarios posibles deberá ser previamente programado .

Entonces, si necesitamos proporcionar un comportamiento dinámico real a un programa, podemos usar la devolución de llamada. Con la devolución de llamada puede indicar por parámetros, un programa para llamar a otro programa que proporciona algunos parámetros previamente definidos y puede esperar algunos resultados ( esta es la firma del contrato o la operación ), por lo que estos resultados pueden ser producidos / procesados ​​por un programa de terceros que no No se sabe previamente.

Esta técnica es la base del polimorfismo aplicado a programas, funciones, objetos y todas las demás unidades de código ejecutadas por computadoras.

El mundo humano utilizado como ejemplo para la devolución de llamada se explica bien cuando está haciendo un trabajo, supongamos que es un pintor ( aquí está el programa principal, que pinta ) y llame a su cliente a veces para pedirle que apruebe el resultado de su trabajo , entonces, decide si la imagen es buena ( su cliente es el programa de terceros ).

En el ejemplo anterior, usted es pintor y "delega" a otros el trabajo para aprobar el resultado, la imagen es el parámetro y cada nuevo cliente (la "función" devuelta) cambia el resultado de su trabajo decidiendo lo que quiere sobre la imagen ( la decisión tomada por los clientes es el resultado devuelto de la "función de devolución de llamada" ).

Espero que esta explicación pueda ser útil.

Luciano
fuente
6

Supongamos que me ibas a dar una tarea potencialmente larga: obtener los nombres de las primeras cinco personas únicas con las que te encuentres. Esto podría llevar días si estoy en un área escasamente poblada. No estás realmente interesado en sentarte en tus manos mientras corro, así que dices: "Cuando tengas la lista, llámame a mi celular y léemela. Aquí está el número".

Me ha dado una referencia de devolución de llamada, una función que se supone que debo ejecutar para poder seguir procesando.

En JavaScript podría verse así:

var lottoNumbers = [];
var callback = function(theNames) {
  for (var i=0; i<theNames.length; i++) {
    lottoNumbers.push(theNames[i].length);
  }
};

db.executeQuery("SELECT name " +
                "FROM tblEveryOneInTheWholeWorld " +
                "ORDER BY proximity DESC " +
                "LIMIT 5", callback);

while (lottoNumbers.length < 5) {
  playGolf();
}
playLotto(lottoNumbers);

Esto probablemente podría mejorarse de muchas maneras. Por ejemplo, podría proporcionar una segunda devolución de llamada: si termina tardando más de una hora, llame al teléfono rojo y dígale a la persona que responde que ha agotado el tiempo de espera.

vapor25
fuente
6

Las devoluciones de llamada se describen más fácilmente en términos del sistema telefónico. Una llamada de función es análoga a llamar a alguien por teléfono, hacerle una pregunta, obtener una respuesta y colgar; agregar una devolución de llamada cambia la analogía para que después de hacerle una pregunta, también le dé su nombre y número para que pueda devolverle la llamada con la respuesta. - Paul Jakubik, "Implementaciones de devolución de llamada en C ++"

DejanLekic
fuente
Una explicación más fácil sería: llamo a alguien, ella está en una reunión, le dejo un número de teléfono, vuelve a llamar.
Solitario
5

Una devolución de llamada es una función que será llamada por una segunda función. Esta segunda función no sabe de antemano a qué función llamará. Entonces, la identidad de la función de devolución de llamada se almacena en algún lugar, o se pasa a la segunda función como parámetro. Esta "identidad", dependiendo del lenguaje de programación, podría ser la dirección de la devolución de llamada, o algún otro tipo de puntero, o podría ser el nombre de la función. El principal es el mismo, almacenamos o pasamos información que identifica inequívocamente la función.

Cuando llegue el momento, la segunda función puede llamar a la devolución de llamada, proporcionando parámetros dependiendo de las circunstancias en ese momento. Incluso podría elegir la devolución de llamada de un conjunto de posibles devoluciones de llamada. El lenguaje de programación debe proporcionar algún tipo de sintaxis para permitir que la segunda función llame a la devolución de llamada, conociendo su "identidad".

Este mecanismo tiene muchos usos posibles. Con las devoluciones de llamada, el diseñador de una función puede permitir que se personalice haciendo que llame a cualquier devolución de llamada que se proporcione. Por ejemplo, una función de clasificación podría tomar una devolución de llamada como parámetro, y esta devolución de llamada podría ser una función para comparar dos elementos para decidir cuál es el primero.

Por cierto, dependiendo del lenguaje de programación, la palabra "función" en la discusión anterior podría ser reemplazada por "bloque", "cierre", "lambda", etc.

David Casseres
fuente
5

Por lo general, enviamos variables a las funciones. Supongamos que tiene una tarea donde la variable necesita ser procesada antes de ser dada como argumento: puede usar la devolución de llamada.

function1(var1, var2) Es la forma habitual.

¿Qué sucede si quiero var2ser procesado y luego enviado como argumento? function1(var1, function2(var2))

Este es un tipo de devolución de llamada, donde function2ejecuta un código y devuelve una variable a la función inicial.

Nishant
fuente
2
¿Qué es otro tipo de devolución de llamada?
johnny
@johnny: Hay devoluciones de llamada normales del navegador que se activan cuando se completa un Ajax, etc.
Nishant
4

Una explicación metafórica:

Tengo un paquete que quiero entregar a un amigo, y también quiero saber cuándo lo recibe mi amigo.

Entonces llevo el paquete a la oficina de correos y les pido que lo entreguen. Si quiero saber cuándo mi amigo recibe el paquete, tengo dos opciones:

(a) Puedo esperar en la oficina de correos hasta que se entregue.

(b) Recibiré un correo electrónico cuando se entregue.

La opción (b) es análoga a una devolución de llamada.

tonylo
fuente
4

Para enseñar devoluciones de llamada, primero debe enseñar el puntero. Una vez que los estudiantes comprendan la idea de puntero a una variable, la idea de devoluciones de llamada será más fácil. Suponiendo que está utilizando C / C ++, se pueden seguir estos pasos.

  • Primero muestre a sus alumnos cómo usar y manipular variables usando punteros junto con los identificadores de variables normales.
  • Luego enséñeles que hay cosas que solo se pueden hacer con punteros (como pasar una variable por referencia).
  • Luego dígales cómo el código ejecutable o las funciones son como algunos otros datos (o variables) en la memoria. Entonces, las funciones también tienen direcciones o punteros.
  • Luego muéstreles cómo se pueden llamar las funciones con punteros de función y dígales que se llaman devoluciones de llamada.
  • Ahora, la pregunta es, ¿por qué todos estos problemas para llamar a algunas funciones? ¿Cuál es el beneficio? Al igual que los punteros de datos, el puntero de función, también conocido como devoluciones de llamada, tiene algunas ventajas sobre el uso de identificadores normales.
  • El primero es que los identificadores de función o los nombres de función no se pueden usar como datos normales. Quiero decir, no puedes hacer una estructura de datos con funciones (como una matriz o una lista vinculada de funciones). Pero con las devoluciones de llamada, puede hacer una matriz, una lista vinculada o usarlos con otros datos como en el diccionario de pares de valores-clave o árboles, o cualquier otra cosa. Este es un poderoso beneficio. Y otros beneficios son en realidad hijos de este.
  • El uso más común de las devoluciones de llamada se ve en la programación de controladores de eventos. Donde se ejecutan una o más funciones en función de alguna señal entrante. Con las devoluciones de llamada, se puede mantener un diccionario para asignar señales con devoluciones de llamada. Entonces, la resolución de la señal de entrada y la ejecución del código correspondiente se vuelven mucho más fáciles.
  • El segundo uso de las devoluciones de llamada que viene a mi mente son las funciones de orden superior. Las funciones que toman otras funciones como argumentos de entrada. Y para enviar funciones como argumentos, necesitamos devoluciones de llamada. Un ejemplo puede ser una función que toma una matriz y una devolución de llamada. Luego realiza la devolución de llamada en cada uno de los elementos de la matriz y devuelve los resultados en otra matriz. Si pasamos a la función una devolución de llamada duplicada, obtenemos una matriz de doble valor. Si pasamos una devolución de llamada al cuadrado, obtenemos cuadrados. Para raíces cuadradas, simplemente envíe la devolución de llamada adecuada. Esto no se puede hacer con funciones normales.

Puede haber muchas más cosas. Involucre a los estudiantes y ellos descubrirán. Espero que esto ayude.

Gulshan
fuente
1
Mi otra respuesta relacionada con este tema en programadores
SE
3

En inglés simple, una devolución de llamada es una promesa. Joe, Jane, David y Samantha comparten un viaje compartido al trabajo. Joe conduce hoy. Jane, David y Samantha tienen un par de opciones:

  1. Revise la ventana cada 5 minutos para ver si Joe está fuera
  2. Sigue haciendo lo suyo hasta que Joe toque el timbre.

Opción 1: Esto es más como un ejemplo de sondeo en el que Jane estaría atrapada en un "bucle" para verificar si Joe está afuera. Jane no puede hacer nada más mientras tanto.

Opción 2: este es el ejemplo de devolución de llamada. Jane le dice a Joe que toque el timbre cuando esté afuera. Ella le da una "función" para tocar el timbre de la puerta. Joe no necesita saber cómo funciona el timbre de la puerta o dónde está, solo necesita llamar a esa función, es decir, tocar el timbre de la puerta cuando esté allí.

Las devoluciones de llamada son impulsadas por "eventos". En este ejemplo, el "evento" es la llegada de Joe. En Ajax, por ejemplo, los eventos pueden ser "exitosos" o "fallidos" de la solicitud asincrónica y cada uno puede tener la misma o diferente devolución de llamada.

En términos de aplicaciones JavaScript y devoluciones de llamada. También necesitamos entender los "cierres" y el contexto de la aplicación. A qué se refiere "esto" puede confundir fácilmente a los desarrolladores de JavaScript. En este ejemplo, dentro del método / devolución de llamada "ring_the_door_bell ()" de cada persona, puede haber algunos otros métodos que cada persona debe hacer según su rutina matutina, por ejemplo. "apagar la televisión()". Queremos que "esto" se refiera al objeto "Jane" o al objeto "David" para que cada uno pueda configurar cualquier otra cosa que necesite antes de que Joe los recoja. Aquí es donde configurar la devolución de llamada con Joe requiere parodiar el método para que "esto" se refiera al objeto correcto.

¡Espero que ayude!

Nael El Shawwa
fuente
3

Una devolución de llamada es un sobre estampado con dirección propia. Cuando llamas a una función, es como enviar una carta. Si desea que esa función llame a otra función, proporcione esa información en forma de referencia o dirección.

pete
fuente
3

Creo que es una tarea bastante fácil de explicar.

Al principio, la devolución de llamada son funciones normales.
Y además, llamamos a esta función (llamémosla A) desde dentro de otra función (llamémosla B).

La magia sobre esto es que yo decido, qué función debe llamar la función desde fuera de B.

En el momento en que escribo la función BI no sé a qué función de devolución de llamada se debe llamar. En el momento en que llamo a la función BI, también le digo a esta función que llame a la función A. Eso es todo.

Yunzen
fuente
3

¿Qué es una función de devolución de llamada?

La respuesta simple a esta primera pregunta es que una función de devolución de llamada es una función que se llama a través de un puntero de función. Si pasa el puntero (dirección) de una función como argumento a otra, cuando ese puntero se usa para llamar a la función a la que apunta, se dice que se realiza una devolución de llamada.

La función de devolución de llamada es difícil de rastrear, pero a veces es muy útil. Especialmente cuando estás diseñando bibliotecas. La función de devolución de llamada es como pedirle a su usuario que le dé un nombre de función, y usted llamará a esa función bajo ciertas condiciones.

Por ejemplo, escribe un temporizador de devolución de llamada. Le permite especificar la duración y qué función llamar, y la función será la devolución de llamada en consecuencia. "Ejecute myfunction () cada 10 segundos durante 5 veces"

O puede crear un directorio de funciones, pasando una lista del nombre de la función y solicitar a la biblioteca que devuelva la llamada en consecuencia. "Devolución de llamada exitosa () si es exitosa, devolución de llamada fallida () si falla".

Veamos un ejemplo simple de puntero de función

void cbfunc()
{
     printf("called");
}

 int main ()
 {
                   /* function pointer */ 
      void (*callback)(void); 
                   /* point to your callback function */ 
      callback=(void *)cbfunc; 
                   /* perform callback */
      callback();
      return 0; 
}

¿Cómo pasar argumentos a la función de devolución de llamada?

Se observó que el puntero de función para implementar la devolución de llamada toma nulo *, lo que indica que puede tomar cualquier tipo de variable, incluida la estructura. Por lo tanto, puede pasar varios argumentos por estructura.

typedef struct myst
{
     int a;
     char b[10];
}myst;

void cbfunc(myst *mt) 
{
     fprintf(stdout,"called %d %s.",mt->a,mt->b); 
}

int main() 
{
       /* func pointer */
    void (*callback)(void *);       //param
     myst m;
     m.a=10;
     strcpy(m.b,"123");       
     callback = (void*)cbfunc;    /* point to callback function */
     callback(&m);                /* perform callback and pass in the param */
     return 0;   
}
Sachin Mhetre
fuente
2

Una devolución de llamada es un método programado para ejecutarse cuando se cumple una condición.

Un ejemplo del "mundo real" es una tienda local de videojuegos. Estás esperando Half-Life 3. En lugar de ir a la tienda todos los días para ver si está dentro, registras tu correo electrónico en una lista para recibir una notificación cuando el juego esté disponible. El correo electrónico se convierte en su "devolución de llamada" y la condición a cumplir es la disponibilidad del juego.

Un ejemplo de "programadores" es una página web en la que desea realizar una acción cuando se hace clic en un botón. Registra un método de devolución de llamada para un botón y continúa realizando otras tareas. Cuando / si el usuario presiona el botón, el navegador mirará la lista de devoluciones de llamada para ese evento y llamará a su método.

Una devolución de llamada es una forma de manejar eventos de forma asincrónica. Nunca puede saber cuándo se ejecutará la devolución de llamada o si se ejecutará en absoluto. La ventaja es que libera su programa y ciclos de CPU para realizar otras tareas mientras espera la respuesta.

Optimista
fuente
Decir que está "programado" podría causar confusión aquí. Las devoluciones de llamada a menudo se usan en sistemas asincrónicos y no habría un "horario" sino un "evento" que desencadene la devolución de llamada para ejecutarse.
Deven Phillips el
2

Claro y simple: una devolución de llamada es una función que se le da a otra función, para que pueda llamarla .

Por lo general, se llama cuando se completa alguna operación. Como crea la devolución de llamada antes de dársela a la otra función, puede inicializarla con información de contexto desde el sitio de la llamada. Es por eso que se llama una llamada * back *: la primera función vuelve a llamar al contexto desde donde se llamó.

Andrei Vajna II
fuente
2

“En la programación de computadoras, una devolución de llamada es una referencia al código ejecutable, o un fragmento de código ejecutable, que se pasa como argumento a otro código. Esto permite que una capa de software de nivel inferior llame a una subrutina (o función) definida en una capa de nivel superior ". - Wikipedia

Devolución de llamada en C usando el puntero de función

En C, la devolución de llamada se implementa utilizando el puntero de función. Puntero de función: como su nombre indica, es un puntero a una función.

Por ejemplo, int (* ptrFunc) ();

Aquí, ptrFunc es un puntero a una función que no toma argumentos y devuelve un entero. NO olvide poner el paréntesis, de lo contrario, el compilador supondrá que ptrFunc es un nombre de función normal, que no toma nada y devuelve un puntero a un entero.

Aquí hay un código para demostrar el puntero de la función.

#include<stdio.h>
int func(int, int);
int main(void)
{
    int result1,result2;
    /* declaring a pointer to a function which takes
       two int arguments and returns an integer as result */
    int (*ptrFunc)(int,int);

    /* assigning ptrFunc to func's address */                    
    ptrFunc=func;

    /* calling func() through explicit dereference */
    result1 = (*ptrFunc)(10,20);

    /* calling func() through implicit dereference */        
    result2 = ptrFunc(10,20);            
    printf("result1 = %d result2 = %d\n",result1,result2);
    return 0;
}

int func(int x, int y)
{
    return x+y;
}

Ahora intentemos comprender el concepto de Callback en C usando el puntero de función.

El programa completo tiene tres archivos: callback.c, reg_callback.h y reg_callback.c.

/* callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* callback function definition goes here */
void my_callback(void)
{
    printf("inside my_callback\n");
}

int main(void)
{
    /* initialize function pointer to
    my_callback */
    callback ptr_my_callback=my_callback;                        
    printf("This is a program demonstrating function callback\n");
    /* register our callback function */
    register_callback(ptr_my_callback);                          
    printf("back inside main program\n");
    return 0;
}

/* reg_callback.h */
typedef void (*callback)(void);
void register_callback(callback ptr_reg_callback);


/* reg_callback.c */
#include<stdio.h>
#include"reg_callback.h"

/* registration goes here */
void register_callback(callback ptr_reg_callback)
{
    printf("inside register_callback\n");
    /* calling our callback function my_callback */
    (*ptr_reg_callback)();                               
}

Si ejecutamos este programa, la salida será

Este es un programa que muestra la función de devolución de llamada dentro de register_callback dentro de my_callback dentro del programa principal

La función de capa superior llama a una función de capa inferior como una llamada normal y el mecanismo de devolución de llamada permite que la función de capa inferior llame a la función de capa superior a través de un puntero a una función de devolución de llamada.

Devolución de llamada en Java usando la interfaz

Java no tiene el concepto de puntero de función Implementa el mecanismo de devolución de llamada a través de su mecanismo de interfaz Aquí, en lugar de un puntero de función, declaramos que una interfaz tiene un método que se llamará cuando el destinatario finalice su tarea

Permítanme demostrarlo a través de un ejemplo:

La interfaz de devolución de llamada

public interface Callback
{
    public void notify(Result result);
}

La persona que llama o la clase de nivel superior

public Class Caller implements Callback
{
Callee ce = new Callee(this); //pass self to the callee

//Other functionality
//Call the Asynctask
ce.doAsynctask();

public void notify(Result result){
//Got the result after the callee has finished the task
//Can do whatever i want with the result
}
}

La función Callee o la capa inferior

public Class Callee {
Callback cb;
Callee(Callback cb){
this.cb = cb;
}

doAsynctask(){
//do the long running task
//get the result
cb.notify(result);//after the task is completed, notify the caller
}
}

Devolución de llamada utilizando el patrón EventListener

  • Elemento de la lista

Este patrón se utiliza para notificar de 0 a n números de observadores / oyentes que una tarea en particular ha finalizado

  • Elemento de la lista

La diferencia entre el mecanismo de devolución de llamada y el mecanismo EventListener / Observer es que en la devolución de llamada, la persona que llama notifica a la persona que llama, mientras que en Eventlisener / Observer, la persona que llama puede notificar a cualquier persona interesada en ese evento (la notificación puede ir a otras partes del aplicación que no ha activado la tarea)

Déjame explicarte a través de un ejemplo.

La interfaz de eventos

public interface Events {

public void clickEvent();
public void longClickEvent();
}

Widget de clase

package com.som_itsolutions.training.java.exampleeventlistener;

import java.util.ArrayList;
import java.util.Iterator;

public class Widget implements Events{

    ArrayList<OnClickEventListener> mClickEventListener = new ArrayList<OnClickEventListener>(); 
    ArrayList<OnLongClickEventListener> mLongClickEventListener = new ArrayList<OnLongClickEventListener>();

    @Override
    public void clickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnClickEventListener> it = mClickEventListener.iterator();
                while(it.hasNext()){
                    OnClickEventListener li = it.next();
                    li.onClick(this);
                }   
    }
    @Override
    public void longClickEvent() {
        // TODO Auto-generated method stub
        Iterator<OnLongClickEventListener> it = mLongClickEventListener.iterator();
        while(it.hasNext()){
            OnLongClickEventListener li = it.next();
            li.onLongClick(this);
        }

    }

    public interface OnClickEventListener
    {
        public void onClick (Widget source);
    }

    public interface OnLongClickEventListener
    {
        public void onLongClick (Widget source);
    }

    public void setOnClickEventListner(OnClickEventListener li){
        mClickEventListener.add(li);
    }
    public void setOnLongClickEventListner(OnLongClickEventListener li){
        mLongClickEventListener.add(li);
    }
}

Botón de clase

public class Button extends Widget{
private String mButtonText;
public Button (){
} 
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}

Casilla de verificación de clase

public class CheckBox extends Widget{
private boolean checked;
public CheckBox() {
checked = false;
}
public boolean isChecked(){
return (checked == true);
}
public void setCheck(boolean checked){
this.checked = checked;
}
}

Clase de actividad

paquete com.som_itsolutions.training.java.exampleeventlistener;

public class Activity implements Widget.OnClickEventListener
{
    public Button mButton;
    public CheckBox mCheckBox;
    private static Activity mActivityHandler;
    public static Activity getActivityHandle(){
        return mActivityHandler;
    }
    public Activity ()
    {
        mActivityHandler = this;
        mButton = new Button();
        mButton.setOnClickEventListner(this);
        mCheckBox = new CheckBox();
        mCheckBox.setOnClickEventListner(this);
        } 
    public void onClick (Widget source)
    {
        if(source == mButton){
            mButton.setButtonText("Thank you for clicking me...");
            System.out.println(((Button) mButton).getButtonText());
        }
        if(source == mCheckBox){
            if(mCheckBox.isChecked()==false){
                mCheckBox.setCheck(true);
                System.out.println("The checkbox is checked...");
            }
            else{
                mCheckBox.setCheck(false);
                System.out.println("The checkbox is not checked...");
            }       
        }
    }
    public void doSomeWork(Widget source){
        source.clickEvent();
    }   
}

Otra clase

public class OtherClass implements Widget.OnClickEventListener{
Button mButton;
public OtherClass(){
mButton = Activity.getActivityHandle().mButton;
mButton.setOnClickEventListner(this);//interested in the click event                        //of the button
}
@Override
public void onClick(Widget source) {
if(source == mButton){
System.out.println("Other Class has also received the event notification...");
}
}

Clase principal

public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Activity a = new Activity();
OtherClass o = new OtherClass();
a.doSomeWork(a.mButton);
a.doSomeWork(a.mCheckBox);
}
}

Como puede ver en el código anterior, tenemos una interfaz llamada eventos que básicamente enumera todos los eventos que pueden ocurrir para nuestra aplicación. La clase Widget es la clase base para todos los componentes de la interfaz de usuario, como Button, Checkbox. Estos componentes de la interfaz de usuario son los objetos que realmente reciben los eventos del código marco. La clase de widget implementa la interfaz de eventos y también tiene dos interfaces anidadas, a saber, OnClickEventListener y OnLongClickEventListener

Estas dos interfaces son responsables de escuchar los eventos que pueden ocurrir en los componentes de la interfaz de usuario derivados del widget como Button o Checkbox. Entonces, si comparamos este ejemplo con el ejemplo anterior de devolución de llamada utilizando la interfaz Java, estas dos interfaces funcionan como la interfaz de devolución de llamada. Entonces el código de nivel superior (Here Activity) implementa estas dos interfaces. Y cada vez que se produzca un evento en un widget, se llamará al código de nivel superior (o al método de estas interfaces implementado en el código de nivel superior, que es aquí Actividad).

Ahora déjenme discutir la diferencia básica entre Callback y el patrón Eventlistener. Como hemos mencionado que usando la devolución de llamada, la persona que llama puede notificar solo a una persona que llama. Pero en el caso del patrón EventListener, cualquier otra parte o clase de la Aplicación puede registrarse para los eventos que pueden ocurrir en el Botón o Casilla de verificación. El ejemplo de este tipo de clase es el OtherClass. Si ve el código de la Otra Clase, encontrará que se ha registrado como un oyente del ClickEvent que puede ocurrir en el Botón definido en la Actividad. La parte interesante es que, además de la Actividad (la persona que llama), esta Otra Clase también se notificará cada vez que ocurra el evento de clic en el Botón.

somenath mukhopadhyay
fuente
1

Callbacks le permite insertar su propio código en otro bloque de código que se ejecutará en otro momento, que modifica o agrega al comportamiento de ese otro bloque de código para satisfacer sus necesidades. Obtiene flexibilidad y personalización al tiempo que puede tener un código más fácil de mantener.

Menos código duro = más fácil de mantener y cambiar = menos tiempo = más valor comercial = genialidad.

Por ejemplo, en javascript, utilizando Underscore.js, puede encontrar todos los elementos pares en una matriz como esta:

var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
=> [2, 4, 6]

Ejemplo cortesía de Underscore.js: http://documentcloud.github.com/underscore/#filter

letuboy
fuente
1

[editado] cuando tenemos dos funciones, digamos functionA y functionB , si functionA depende de functionB .

luego llamamos a functionB como una función de devolución de llamada . Esto se usa ampliamente en Spring Framework.

función de devolución de llamada ejemplo de wikipedia

Balaswamy Vaddeman
fuente
1

Piense en un método como darle una tarea a un compañero de trabajo. Una tarea simple podría ser la siguiente:

Solve these equations:
x + 2 = y
2 * x = 3 * y

Su compañero de trabajo diligentemente hace los cálculos y le da el siguiente resultado:

x = -6
y = -4

Pero su compañero de trabajo tiene un problema, no siempre comprende las anotaciones, como ^, pero las comprende por su descripción. Tales como exponent. Cada vez que encuentra uno de estos, obtienes lo siguiente:

I don't understand "^"

Esto requiere que vuelva a escribir todo su conjunto de instrucciones nuevamente después de explicar lo que el personaje significa para su compañero de trabajo, y él no siempre recuerda entre preguntas. Y también tiene dificultades para recordar tus consejos, como preguntarme. Sin embargo, siempre sigue tus instrucciones escritas lo mejor que puede.

Piensa en una solución, solo agrega lo siguiente a todas sus instrucciones:

If you have any questions about symbols, call me at extension 1234 and I will tell you its name.

Ahora, cuando tiene un problema, lo llama y le pregunta, en lugar de darle una mala respuesta y hacer que el proceso se reinicie.

Guvante
fuente
0

Esto en términos de descarga de una página web:

Su programa se ejecuta en un teléfono celular y solicita la página web http://www.google.com . Si escribe su programa sincrónicamente, la función que escribe para descargar los datos se ejecutará continuamente hasta que se descarguen todos los datos. Esto significa que su IU no se actualizará y básicamente aparecerá congelada. Si escribe su programa utilizando devoluciones de llamada, solicita los datos y dice "ejecutar esta función cuando haya terminado". Esto permite que la interfaz de usuario todavía permita la interacción del usuario mientras se descarga el archivo. Una vez que la página web ha finalizado la descarga, se llama a su función de resultado (devolución de llamada) y puede manejar los datos.

Básicamente, le permite solicitar algo y continuar ejecutando mientras espera el resultado. Una vez que el resultado vuelve a usted a través de una función de devolución de llamada, puede retomar la operación donde la dejó.

sokket
fuente