language agnostic - ¿Qué es una función de devolución de llamada?
language-agnostic callback (20)
¿Qué es la devolución de llamada ?
- En general, una llamada telefónica realizada para devolver una que alguien ha recibido.
- En computación, una devolución de llamada es una pieza de código ejecutable que se pasa como un argumento a otro código. Cuando la función se realiza con su trabajo (o cuando ocurre algún evento), llama a su función de devolución de llamada (le devuelve la llamada, de ahí el nombre).
¿Qué es una función de devolución de llamada ?
- una función de devolución de llamada es como un servidor que "devuelve la llamada" a su Maestro cuando ha completado una tarea.
una función de devolución de llamada es una función que se pasa a otra función (llamemos a esta otra función
otherFunction
) como un parámetro, y la función de devolución de llamada se llama (o ejecuta) dentro de la otraotherFunction
.acción de función (x, y, devolución de llamada) {devolver devolución de llamada (x, y); }
multiplicación de funciones (x, y) {return x * y; }
suma de funciones (x, y) {return x + y; }
alerta (acción (10, 10, multiplicación)); // salida: 100
alerta (acción (10, 10, adición)); // salida: 20
En SOA, la devolución de llamada permite que los módulos de complemento accedan a los servicios desde el contenedor / entorno.
Analogía: devoluciones de llamada. Asincrónico. Sin bloqueo
Ejemplo de la vida real para devolución de llamada.
¿Qué es una función de devolución de llamada?
Definición opaca
Una función de devolución de llamada es una función que proporciona a otro fragmento de código, lo que permite que ese código lo llame.
Ejemplo elaborado
Por qué querrías hacer esto? Digamos que hay un servicio que necesita invocar. Si el servicio vuelve inmediatamente, usted simplemente:
- Llámalo
- Espera el resultado
- Continuar una vez que llegue el resultado.
Por ejemplo, supongamos que el servicio fuera la función factorial
. Cuando quieras el valor de 5!
, invocaría factorial(5)
, y ocurrirían los siguientes pasos:
Tu ubicación de ejecución actual se guarda (en la pila, pero eso no es importante)
La ejecución se entrega a
factorial
Cuando el
factorial
completa, coloca el resultado en un lugar al que puedes llegar.La ejecución vuelve a donde estaba en [1]
Ahora suponga que factorial
tomó mucho tiempo, porque le está dando grandes números y necesita ejecutarse en algún clúster de supercomputación en algún lugar. Supongamos que espera que le lleve 5 minutos devolver el resultado. Tú podrías:
Mantenga su diseño y ejecute su programa por la noche cuando esté dormido, de modo que no esté mirando la pantalla la mitad del tiempo
Diseña tu programa para hacer otras cosas mientras
factorial
está haciendo lo suyo.
Si elige la segunda opción, las devoluciones de llamada podrían funcionar para usted.
Diseño de extremo a extremo
Para explotar un patrón de devolución de llamada, lo que desea es poder llamar factorial
de la siguiente manera:
factorial(really_big_number, what_to_do_with_the_result)
El segundo parámetro, what_to_do_with_the_result
, es una función que envía junto a factorial
, con la esperanza de que factorial
lo llame a su resultado antes de regresar.
Sí, esto significa que el factorial
debe haberse escrito para admitir las devoluciones de llamada.
Ahora suponga que desea poder pasar un parámetro a su devolución de llamada. Ahora no puedes, porque no lo vas a llamar, factorial
es. Por lo tanto, se debe escribir factorial
para permitirle pasar sus parámetros, y solo los entregará a su devolución de llamada cuando la invoque. Podría verse así:
factorial (number, callback, params)
{
result = number! // i can make up operators in my pseudocode
callback (result, params)
}
Ahora que el factorial
permite este patrón, su devolución de llamada podría verse así:
logIt (number, logger)
{
logger.log(number)
}
y tu llamada a factorial
seria
factorial(42, logIt, logger)
¿Qué pasa si quieres devolver algo desde logIt
? Bueno, no puedes, porque el factorial
no le está prestando atención.
Bueno, ¿por qué no puede devolver factorial
lo que devuelve su devolución de llamada?
Haciéndolo no bloqueante
Dado que la ejecución debe entregarse a la devolución de llamada cuando el factorial
finaliza, realmente no debería devolver nada a quien llama. E idealmente, iniciaría su trabajo en otro subproceso / proceso / máquina y regresaría inmediatamente para que pueda continuar, tal vez algo como esto:
factorial(param_1, param_2, ...)
{
new factorial_worker_task(param_1, param_2, ...);
return;
}
Esta es ahora una "llamada asíncrona", lo que significa que cuando la llamas, vuelve de inmediato, pero aún no ha hecho su trabajo. Por lo tanto, necesita mecanismos para verificarlo y obtener su resultado cuando finalice, y su programa se ha vuelto más complejo en el proceso.
Y, por cierto, al usar este patrón, factorial_worker_task
puede iniciar su devolución de llamada de forma asíncrona y regresar inmediatamente.
Entonces, ¿Qué haces?
La respuesta es permanecer dentro del patrón de devolución de llamada. Cuando quieras escribir
a = f()
g(a)
y f
se debe llamar de forma asíncrona, en lugar de eso escribirá
f(g)
donde g
se pasa como una devolución de llamada.
Esto cambia fundamentalmente la topología de flujo de su programa , y requiere cierto tiempo para acostumbrarse.
Su lenguaje de programación podría ayudarlo mucho al brindarle una manera de crear funciones sobre la marcha. En el código inmediatamente anterior, la función g
podría ser tan pequeña como print (2*a+1)
. Si su idioma requiere que lo defina como una función separada, con un nombre y una firma totalmente innecesarios, entonces su vida se volverá desagradable si usa este patrón mucho.
Si, por otro lado, su idioma le permite crear lambdas, entonces está en mucho mejor estado. Entonces terminarás escribiendo algo como
f( func(a) { print(2*a+1); })
que es mucho mejor
Cómo pasar la devolución de llamada
¿Cómo pasaría la función de devolución de llamada a factorial
? Bueno, podrías hacerlo de varias maneras.
Si la función llamada se ejecuta en el mismo proceso, podría pasar un puntero a la función
O tal vez quiera mantener un diccionario de
fn name --> fn ptr
en su programa, en cuyo caso podría pasar el nombreTal vez su idioma le permita definir la función en el lugar, ¡posible como un lambda! Internamente, está creando algún tipo de objeto y pasando un puntero, pero no tiene que preocuparse por eso.
Tal vez la función a la que está llamando se esté ejecutando en una máquina completamente separada, y la esté utilizando usando un protocolo de red como HTTP. Podría exponer su devolución de llamada como una función de llamada HTTP y pasar su URL.
Tienes la idea
El reciente aumento de las devoluciones de llamada
En esta era web en la que hemos ingresado, los servicios que invocamos a menudo están a través de la red. A menudo no tenemos ningún control sobre esos servicios, es decir, no los escribimos, no los mantenemos, no podemos asegurarnos de que estén funcionando o de cómo funcionan.
Pero no podemos esperar que nuestros programas se bloqueen mientras esperamos que estos servicios respondan. Al ser conscientes de esto, los proveedores de servicios a menudo diseñan API utilizando el patrón de devolución de llamada.
JavaScript soporta devoluciones de llamada muy bien, por ejemplo, con lambdas y cierres. Y hay mucha actividad en el mundo de JavaScript, tanto en el navegador como en el servidor. Incluso hay plataformas de JavaScript que están siendo desarrolladas para móviles.
A medida que avancemos, más y más de nosotros escribiremos código asíncrono, para lo cual esta comprensión será esencial.
“En la programación de computadoras, una devolución de llamada es una referencia al código ejecutable, o una pieza de código ejecutable, que se pasa como un 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 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 entre paréntesis, de lo contrario el compilador asumirá 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 entender el concepto de devolución de llamada 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 de 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 a la función de capa inferior llamar 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 la interfaz de uso de Java
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 una interfaz con un método que se llamará cuando el destinatario finalice su tarea.
Déjame 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 lista
Este patrón se utiliza para notificar a 0 a n números de observadores / oyentes que una tarea particular ha finalizado
- Elemento de 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 solo, mientras que en Eventlisener / Observer, la persona llamada puede notificar a cualquier persona interesada en ese evento (la notificación puede dirigirse a otras partes del aplicación que no ha activado la tarea)
Déjame explicarlo 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;
}
}
Class Checkbox
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
package 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 lista todos los eventos que pueden suceder 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 de marco. La clase de widgets 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 que utiliza la interfaz Java, estas dos interfaces funcionan como la interfaz de devolución de llamada. Así que el código de nivel superior (Actividad aquí) implementa estas dos interfaces. Y siempre 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 se encuentra aquí Actividad).
Ahora permítanme hablar sobre la diferencia básica entre el patrón de Devolución de llamada y Eventlistener. Como hemos mencionado que al utilizar 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 OtherClass. Si ve el código de OtherClass, encontrará que se ha registrado como oyente del evento de clic que puede ocurrir en el botón definido en la actividad. Una parte interesante es que, además de la Actividad (el Llamante), esta Otra Clase también será notificada cuando ocurra el evento de clic en el Botón.
Creo que esta jerga de "devolución de llamada" se ha utilizado erróneamente en muchos lugares. Mi definición sería algo como:
Una función de devolución de llamada es una función que se pasa a alguien y permite que la llame en algún momento.
Creo que la gente acaba de leer la primera oración de la definición de wiki:
una devolución de llamada es una referencia al código ejecutable, o una pieza de código ejecutable, que se pasa como un argumento a otro código.
He estado trabajando con muchas API, vea varios ejemplos malos. Muchas personas tienden a nombrar un puntero de función (una referencia a un código ejecutable) o funciones anónimas (una pieza de código ejecutable) "devolución de llamada", si son solo funciones, ¿por qué necesita otro nombre para esto?
En realidad, solo la segunda oración en la definición de wiki revela las diferencias entre una función de devolución de llamada y una función normal:
Esto permite que una capa de software de nivel inferior llame a una subrutina (o función) definida en una capa de nivel superior.
así que la diferencia es a quién le pasará la función y cómo se llamará a su función pasada. Si solo define una función y la pasa a otra función y la llama directamente en el cuerpo de esa función, no lo llame una devolución de llamada. La definición dice que su función pasada será llamada por la función de "nivel inferior".
Espero que la gente pueda dejar de usar esta palabra en un contexto ambiguo, no puede ayudar a la gente a entender mejor, solo peor.
Esto hace que las devoluciones de llamada suenen como declaraciones de retorno al final de los métodos.
No estoy seguro de que sean lo que son.
Creo que las devoluciones de llamada son en realidad una llamada a una función, como consecuencia de la invocación y finalización de otra función.
También creo que las devoluciones de llamada están destinadas a abordar la invocación originaria, en una especie de "¡hey! ¿Esa cosa que pediste? Lo he hecho, solo pensé que te lo haría saber, de vuelta a ti".
La respuesta simple a esta 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 un argumento a otro, cuando ese puntero se usa para llamar a la función a la que señala, se dice que se realiza una devolución de llamada.
Los desarrolladores a menudo se confunden por lo que es una devolución de llamada debido al nombre de la maldita cosa.
Una función de devolución de llamada es una función que es:
- accesible por otra función, y
- se invoca después de la primera función si esa primera función se completa
Una buena manera de imaginar cómo funciona una función de devolución de llamada es que es una función que se " llama desde atrás " de la función a la que se le pasa.
Tal vez un nombre mejor sería una función de "llamada después" .
Esta construcción es muy útil para el comportamiento asíncrono, donde queremos que se lleve a cabo una actividad cada vez que se completa un evento anterior.
Pseudocódigo
// A function which accepts another function as an argument
// (and will automatically invoke that function when it completes - note that there is no explicit call to callbackFunction)
funct printANumber(int number, funct callbackFunction) {
printout("The number you provided is: " + number);
}
// a function which we will use in a driver function as a callback function
funct printFinishMessage() {
printout("I have finished printing numbers.");
}
// Driver method
funct event() {
printANumber(6, printFinishMessage);
}
Resultado si llamaste evento ():
The number you provided is: 6
I have finished printing numbers.
El orden de la salida aquí es importante. Dado que las funciones de devolución de llamada se llaman después, "He terminado de imprimir números" se imprime en último lugar, no primero.
Las devoluciones de llamada se denominan debido a su uso con lenguajes de puntero. Si no usa uno de estos, no utilice el nombre ''devolución de llamada''. Simplemente entienda que es solo un nombre para describir un método que se proporciona como un argumento a otro método, de modo que cuando se llama al método principal (cualquiera sea la condición, como hacer clic en un botón, una marca del temporizador, etc.) y su cuerpo del método se completa, Entonces se invoca la función de devolución de llamada.
Algunos lenguajes admiten construcciones en las que se admiten varios argumentos de la función de devolución de llamada, y se llaman en función de cómo se completa la función principal (es decir, se llama a una devolución de llamada en el caso de que la función principal se complete con éxito, se llama a otro en el caso de que la función principal arroje un error específico, etc).
Seamos sencillos. ¿Qué es una función de devolución de llamada?
Ejemplo de parábola y analogía
Tengo una secretaria Todos los días le pido que: (i) deje el correo saliente de la empresa en la oficina de correos, y después de que haya hecho eso, haga lo siguiente: (ii) cualquier tarea que escribí para ella en una de esas notas adhesivas .
Ahora, ¿cuál es la tarea en la nota adhesiva? La tarea varía de un día para otro.
Supongamos que en este día en particular, le pido que imprima algunos documentos. Así que escribo eso en la nota adhesiva, y lo coloco en su escritorio junto con el correo saliente que necesita publicar.
En resumen:
- Primero, ella tiene que dejar el correo y
- Inmediatamente después de hacer eso, ella necesita imprimir algunos documentos.
La función de devolución de llamada es la segunda tarea: imprimir esos documentos. Porque se hace DESPUÉS de que se deje el correo, y también porque se le entrega la nota adhesiva que le dice que imprima el documento junto con el correo que más necesita.
Vamos a unir esto con el vocabulario de programación.
- El nombre del método en este caso es: DropOffMail.
- Y la función de devolución de llamada es: PrintOffDocuments. PrintOffDocuments es la función de devolución de llamada porque queremos que la secretaria haga eso, solo después de que DropOffMail se haya ejecutado.
- Así que "pasaré: PrintOffDocuments como un" argumento "al método DropOffMail. Este es un punto importante.
Eso es todo lo que es. Nada mas. Espero haberlo aclarado, y si no, publique un comentario y haré todo lo posible para aclararlo.
Supongamos que tenemos una función sort(int *arraytobesorted,void (*algorithmchosen)(void))
donde puede aceptar un puntero a función como su argumento, que puede usarse en algún momento en la implementación de sort()
. Entonces, aquí el código que está siendo direccionado por la función puntero algorithmchosen
se llama como función de devolución de llamada .
Y ver que la ventaja es que podemos elegir cualquier algoritmo como:
1. algorithmchosen = bubblesort
2. algorithmchosen = heapsort
3. algorithmchosen = mergesort ...
Los cuales fueron, digamos, se han implementado con el prototipo:
1. `void bubblesort(void)`
2. `void heapsort(void)`
3. `void mergesort(void)` ...
Este es un concepto utilizado para lograr el polimorfismo en la programación orientada a objetos.
Tenga en cuenta que la devolución de llamada es una palabra.
La página de devolución de llamada de wikipedia lo explica muy bien.
cita de la página de wikipedia:
En la programación de computadoras, una devolución de llamada es una referencia al código ejecutable, o una pieza de código ejecutable, que se pasa como un 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.
Una función de devolución de llamada es aquella que se debe llamar cuando se cumple una determinada condición. En lugar de ser llamado inmediatamente, la función de devolución de llamada se llama en un momento determinado en el futuro.
Normalmente, se utiliza cuando se inicia una tarea que finalizará de forma asíncrona (es decir, finalizará algún tiempo después de que haya regresado la función de llamada).
Por ejemplo, una función para solicitar una página web puede requerir que su interlocutor proporcione una función de devolución de llamada a la que se llamará cuando la página haya finalizado la descarga.
Una función de devolución de llamada es una función que especifica para una función / método existente, que se invoca cuando se completa una acción, requiere un procesamiento adicional, etc.
En Javascript, o más específicamente jQuery, por ejemplo, puede especificar un argumento de devolución de llamada para que se llame cuando una animación haya terminado.
En PHP, la función preg_replace_callback()
permite proporcionar una función a la que se llamará cuando la expresión regular coincida, pasando la (s) cadena (s) que coinciden como argumentos.
Una respuesta simple sería que se trata de una función que no es llamada por usted, sino por el usuario o por el navegador después de que haya ocurrido un evento determinado o después de que se haya procesado algún código.
mira la imagen :)
El programa principal llama a la función de biblioteca (que también podría ser una función a nivel del sistema) con el nombre de la función de devolución de llamada. Esta función de devolución de llamada podría implementarse de múltiples maneras. El programa principal elige una devolución de llamada según el requisito.
Finalmente, la función de biblioteca llama a la función de devolución de llamada durante la ejecución.
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 ++"
Función de devolución de llamada Una función que pasó a otra función como un argumento.
function test_function(){
alert("Hello world");
}
setTimeout(test_function, 2000);
Nota: en el ejemplo anterior, test_function se usa como un argumento para la función setTimeout.
Llamada después sería un nombre mejor que el nombre estúpido, devolución de llamada . Cuando o si se cumple una condición dentro de una función, llame a otra función, la función Llamada después , la que se recibió como argumento.
En lugar de codificar una función interna dentro de una función, uno escribe una función para aceptar una función de Call After ya escrita como argumento. El Call After podría ser llamado en función de los cambios de estado detectados por el código en la función que recibe el argumento.
Una función de devolución de llamada, también conocida como función de orden superior, es una función que se pasa a otra función como parámetro, y la función de devolución de llamada se llama (o ejecuta) dentro de la función principal.
$("#button_1").click(function() {
alert("button 1 Clicked");
});
Aquí hemos pasado una función como parámetro al método de clic. Y el método de clic llamará (o ejecutará) la función de devolución de llamada que le pasamos.
Un área de uso importante es que registre una de sus funciones como un identificador (es decir, una devolución de llamada) y luego envíe un mensaje / llame a alguna función para realizar algún trabajo o procesamiento. Ahora, una vez que se realiza el procesamiento, la función llamada llamará a nuestra función registrada (es decir, ahora se realiza la devolución de llamada), lo que indica que el procesamiento se ha realizado.
Este enlace de wikipedia explica bastante bien gráficamente.
Una función de devolución de llamada es una función que pasa (como referencia o puntero) a una determinada función u objeto. Esta función u objeto devolverá esta función en cualquier momento posterior, posiblemente varias veces, para cualquier tipo de propósito:
- notificar el final de una tarea
- solicitando comparación entre dos elementos (como en c qsort ())
- reportar el progreso de un proceso
- notificar eventos
- Delegar la instanciación de un objeto.
- delegando la pintura de un área
...
Por lo tanto, la descripción de una devolución de llamada como una función a la que se llama al final de otra función o tarea se simplifica demasiado (incluso si es un caso de uso común).