O que é uma função de retorno de chamada?
O que é uma função de retorno de chamada?
Respostas:
Os desenvolvedores geralmente ficam confusos com o que é um retorno de chamada por causa do nome da coisa amaldiçoada.
Uma função de retorno de chamada é uma função que é:
Uma boa maneira de imaginar como funciona uma função de retorno de chamada é que ela é " chamada na parte de trás" " da função para a qual é passada.
Talvez um nome melhor seria um "ligar depois" .
Essa construção é muito útil para comportamento assíncrono, onde queremos que uma atividade ocorra sempre que um evento anterior for concluído.
Pseudo-có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 se você chamou event ():
The number you provided is: 6
I have finished printing numbers.
A ordem da saída aqui é importante. Como as funções de retorno de chamada são chamadas posteriormente, "Eu terminei de imprimir números" é impresso por último, não primeiro.
Os retornos de chamada são chamados devido ao uso nos idiomas dos ponteiros. Se você não usar um desses, não trabalhe com o nome 'callback'. Entenda que é apenas um nome para descrever um método que é fornecido como argumento para outro método, de modo que, quando o método pai é chamado (qualquer condição, como um clique no botão, um tique de timer etc.) e seu corpo é concluído, a função de retorno de chamada é então invocada.
Alguns idiomas suportam construções nas quais vários argumentos da função de retorno de chamada são suportados e são chamados com base em como a função pai é concluída (ou seja, um retorno de chamada é chamado no caso em que a função pai é concluída com êxito, outro é chamado no caso em que a função pai lança um erro específico, etc).
once its parent method completes, the function which this argument represents is then called
. Então, se a função é passada para outra função como argumento, mas é chamada a partir do meio do tempo de execução da função pai parent(cb) {dostuff1(); cb(); dostuff2()}
, ela não é considerada uma callback
função?
Uma função de retorno de chamada é uma função que você fornece a outro trecho de código, permitindo que ela seja chamada por esse código.
Por que você quer fazer isso? Digamos que exista um serviço que você precise chamar. Se o serviço retornar imediatamente, você apenas:
Por exemplo, suponha que o serviço fosse a factorial
função. Quando você deseja o valor de 5!
, invoca factorial(5)
e as seguintes etapas ocorrem:
Seu local de execução atual é salvo (na pilha, mas isso não é importante)
A execução é entregue a factorial
Quando factorial
concluído, coloca o resultado em algum lugar que você pode chegar a ele
A execução volta para onde estava [1]
Agora, suponha que factorial
demorou muito tempo, porque você está dando números enormes e ele precisa ser executado em algum cluster de supercomputação em algum lugar. Digamos que você espere 5 minutos para retornar seu resultado. Você poderia:
Mantenha seu design e execute seu programa à noite quando estiver dormindo, para não ficar olhando a tela metade do tempo
Crie seu programa para fazer outras coisas enquanto factorial
estiver fazendo
Se você escolher a segunda opção, os retornos de chamada poderão funcionar para você.
Para explorar um padrão de retorno de chamada, o que você deseja é poder chamar factorial
da seguinte maneira:
factorial(really_big_number, what_to_do_with_the_result)
O segundo parâmetro,, what_to_do_with_the_result
é uma função para a qual você envia factorial
, na esperança de factorial
chamá-lo em seu resultado antes de retornar.
Sim, isso significa que factorial
precisa ter sido escrito para oferecer suporte a retornos de chamada.
Agora, suponha que você queira passar um parâmetro para seu retorno de chamada. Agora você não pode, porque não vai chamá-lo, factorial
é. Portanto, ele factorial
precisa ser gravado para permitir que você transmita seus parâmetros e os entregará ao retorno de chamada quando o chamar. Pode ser assim:
factorial (number, callback, params)
{
result = number! // i can make up operators in my pseudocode
callback (result, params)
}
Agora que factorial
permite esse padrão, seu retorno de chamada pode ser assim:
logIt (number, logger)
{
logger.log(number)
}
e sua chamada para factorial
seria
factorial(42, logIt, logger)
E se você quiser devolver algo logIt
? Bem, você não pode, porquefactorial
não está prestando atenção a isso.
Bem, por que não factorial
basta retornar o que seu retorno de chamada retorna?
Como a execução deve ser entregue ao retorno de chamada quando factorial
terminar, ela realmente não deve retornar nada ao chamador. E, idealmente, de alguma forma, lançaria seu trabalho em outro encadeamento / processo / máquina e retornaria imediatamente para que você pudesse continuar, talvez algo como isto:
factorial(param_1, param_2, ...)
{
new factorial_worker_task(param_1, param_2, ...);
return;
}
Agora, essa é uma "chamada assíncrona", o que significa que, quando você a chama, ela retorna imediatamente, mas ainda não fez seu trabalho. Portanto, você precisa de mecanismos para verificá-lo e obter seu resultado quando terminar, e seu programa ficou mais complexo no processo.
A propósito, usando esse padrão, você factorial_worker_task
pode iniciar seu retorno de chamada de forma assíncrona e retornar imediatamente.
A resposta é permanecer dentro do padrão de retorno de chamada. Sempre que você quiser escrever
a = f()
g(a)
e f
deve ser chamado de forma assíncrona, você escreverá
f(g)
onde g
é passado como retorno de chamada.
Isso muda fundamentalmente a topologia de fluxo do seu programa e leva algum tempo para se acostumar.
Sua linguagem de programação pode ajudá-lo muito, oferecendo uma maneira de criar funções on-the-fly. No código imediatamente acima, a função g
pode ser tão pequena quantoprint (2*a+1)
. Se o seu idioma exigir que você defina isso como uma função separada, com um nome e uma assinatura totalmente desnecessários, sua vida ficará desagradável se você usar muito esse padrão.
Se, por outro lado, a sua linguagem permite criar lambdas, você está em uma forma muito melhor. Você acabará escrevendo algo como
f( func(a) { print(2*a+1); })
o que é muito melhor.
Como você passaria a função de retorno de chamada factorial
? Bem, você poderia fazer isso de várias maneiras.
Se a função chamada estiver sendo executada no mesmo processo, você poderá passar um ponteiro de função
Ou talvez você queira manter um dicionário fn name --> fn ptr
no seu programa, caso em que você pode passar o nome
Talvez seu idioma permita que você defina a função no local, possível como um lambda! Internamente, ele cria algum tipo de objeto e passa um ponteiro, mas você não precisa se preocupar com isso.
Talvez a função que você está chamando esteja sendo executada em uma máquina totalmente separada e você esteja chamando-a usando um protocolo de rede como HTTP. Você pode expor seu retorno de chamada como uma função que pode ser chamada por HTTP e passar seu URL.
Você entendeu a ideia.
Nesta era da web em que entramos, os serviços que chamamos geralmente estão na rede. Geralmente, não temos controle sobre esses serviços, ou seja, não os escrevemos, não os mantemos, não podemos garantir que eles estejam funcionando ou que estejam funcionando.
Mas não podemos esperar que nossos programas sejam bloqueados enquanto aguardamos a resposta desses serviços. Consciente disso, os provedores de serviços geralmente projetam APIs usando o padrão de retorno de chamada.
O JavaScript suporta retornos de chamada muito bem, por exemplo, com lambdas e fechamentos. E há muita atividade no mundo JavaScript, tanto no navegador quanto no servidor. Existem até plataformas JavaScript sendo desenvolvidas para dispositivos móveis.
À medida que avançamos, cada vez mais pessoas escrevem código assíncrono, para o qual esse entendimento será essencial.
Observe que o retorno de chamada é uma palavra.
A página de retorno de chamada da Wikipedia explica muito bem.
citação da página da wikipedia:
Na programação de computadores, um retorno de chamada é uma referência ao código executável, ou uma parte do código executável, que é passada como argumento para outro código. Isso permite que uma camada de software de nível inferior chame uma sub-rotina (ou função) definida em uma camada de nível superior.
Uma função de retorno de chamada é aquela que deve ser chamada quando uma determinada condição for atendida. Em vez de ser chamada imediatamente, a função de retorno de chamada é chamada em um determinado ponto no futuro.
Normalmente, é usado quando uma tarefa está sendo iniciada que termina de forma assíncrona (ou seja, termina algum tempo após o retorno da função de chamada).
Por exemplo, uma função para solicitar uma página da Web pode exigir que o chamador forneça uma função de retorno de chamada que será chamada quando a página da Web terminar o download.
"...when a condition is met"
mas eu pensei que os retornos de chamada são chamados quando a função pai termina a execução e não depende das condições (?).
Os retornos de chamada são descritos com mais facilidade em termos de sistema telefônico. Uma chamada de função é análoga a ligar para alguém no telefone, fazer uma pergunta, obter uma resposta e desligar; adicionar um retorno de chamada altera a analogia para que, depois de fazer uma pergunta, você também forneça seu nome e número para que ela possa ligar de volta com a resposta.
- Paul Jakubik, "Implementações de retorno de chamada em C ++"
Acredito que esse jargão de "retorno de chamada" tenha sido usado por engano em muitos lugares. Minha definição seria algo como:
Uma função de retorno de chamada é uma função que você transmite a alguém e permite que ela o chame em algum momento.
Eu acho que as pessoas acabam de ler a primeira frase da definição da wiki:
um retorno de chamada é uma referência ao código executável, ou uma parte do código executável, que é passada como argumento para outro código.
Eu tenho trabalhado com muitas APIs, veja vários exemplos ruins. Muitas pessoas tendem a nomear um ponteiro de função (uma referência ao código executável) ou funções anônimas (uma parte do código executável) de "retorno de chamada", se são apenas funções, por que você precisa de outro nome para isso?
Na verdade, apenas a segunda frase na definição do wiki revela as diferenças entre uma função de retorno de chamada e uma função normal:
Isso permite que uma camada de software de nível inferior chame uma sub-rotina (ou função) definida em uma camada de nível superior.
então a diferença é para quem você vai passar a função e como sua função passada será chamada. Se você acabou de definir uma função e passá-la para outra função e a chamou diretamente no corpo da função, não a chame de retorno de chamada. A definição diz que sua função passada será chamada pela função "nível inferior".
Espero que as pessoas possam parar de usar essa palavra em um contexto ambíguo, isso não pode ajudar as pessoas a entender melhor, apenas pior.
Vamos simplificar. O que é uma função de retorno de chamada?
Exemplo por Parábola e Analogia
Eu tenho uma secretária Todos os dias peço que ela: (i) entregue as correspondências enviadas pela empresa nos correios e, depois que ela o faça, faça: (ii) qualquer tarefa que eu escrevi para ela em uma dessas anotações .
Agora, qual é a tarefa do lembrete? A tarefa varia de dia para dia.
Suponha que nesse dia em particular exija que ela imprima alguns documentos. Então, escrevo isso no bilhete e colo na mesa dela, junto com as correspondências que ela precisa postar.
Em suma:
A função de retorno de chamada é a segunda tarefa: imprimir esses documentos. Porque isso é feito APÓS o e-mail cair, e também porque a nota pegajosa solicitando que ela imprima o documento é fornecida juntamente com o e-mail que ela precisa postar.
Vamos agora ligar isso ao vocabulário de programação
Isso é tudo. Nada mais. Espero que isso tenha esclarecido tudo para você - e, se não, poste um comentário e farei o possível para esclarecer.
Isso faz com que os retornos de chamada soem como instruções de retorno no final dos métodos.
Não tenho certeza de que são isso.
Eu acho que os retornos de chamada são realmente uma chamada para uma função, como conseqüência de outra função ser chamada e concluída.
Eu também acho que os retornos de chamada têm como objetivo tratar da invocação originária, em uma espécie de "ei! A coisa que você pediu? Eu fiz isso - apenas pensei em avisar você - de volta para você".
O que é retorno de chamada ?
O que é uma função de retorno de chamada ?
otherFunction
) como parâmetro, e a função de retorno de chamada é chamada (ou executada) dentro do otherFunction
. function action(x, y, callback) {
return callback(x, y);
}
function multiplication(x, y) {
return x * y;
}
function addition(x, y) {
return x + y;
}
alert(action(10, 10, multiplication)); // output: 100
alert(action(10, 10, addition)); // output: 20
Na SOA, o retorno de chamada permite que os Módulos de Plugin acessem serviços do contêiner / ambiente.
Analogia: retornos de chamada. Assíncrono. Exemplo da vida real sem bloqueio
para retorno de chamada
Chamar depois seria um nome melhor do que o nome estúpido, retorno de chamada . Quando ou se a condição for atendida em uma função, chame outra função, a função Chamar Após , aquela recebida como argumento.
Em vez de codificar uma função interna dentro de uma função, alguém escreve uma função para aceitar uma função Call After já escrita como argumento. A chamada após pode ser chamada com base nas alterações de estado detectadas pelo código na função que recebe o argumento.
Uma função de retorno de chamada é uma função que você especifica para uma função / método existente, a ser invocada quando uma ação é concluída, requer processamento adicional etc.
Em Javascript, ou mais especificamente jQuery, por exemplo, você pode especificar um argumento de retorno de chamada a ser chamado quando uma animação terminar.
No PHP, a preg_replace_callback()
função permite fornecer uma função que será chamada quando a expressão regular for correspondida, passando a (s) string (s) correspondente (s) como argumento.
olha a imagem :)
O programa principal chama a função de biblioteca (que também pode ser uma função no nível do sistema) com o nome da função de retorno de chamada. Essa função de retorno de chamada pode ser implementada de várias maneiras. O programa principal escolhe um retorno de chamada conforme o requisito.
Finalmente, a função de biblioteca chama a função de retorno de chamada durante a execução.
A resposta simples para essa pergunta é que uma função de retorno de chamada é uma função chamada por meio de um ponteiro de função. Se você passar o ponteiro (endereço) de uma função como argumento para outro, quando esse ponteiro é usado para chamar a função, ele aponta para ele e diz que é feita uma chamada de retorno.
Suponha que temos uma função na sort(int *arraytobesorted,void (*algorithmchosen)(void))
qual ele pode aceitar um ponteiro de função como argumento, que pode ser usado em algum momento da sort()
implementação. Então, aqui o código que está sendo endereçado pelo ponteiro da função algorithmchosen
é chamado como função de retorno de chamada .
E veja a vantagem é que podemos escolher qualquer algoritmo como:
1. algorithmchosen = bubblesort
2. algorithmchosen = heapsort
3. algorithmchosen = mergesort ...
Quais foram, digamos, implementados com o protótipo:
1. `void bubblesort(void)`
2. `void heapsort(void)`
3. `void mergesort(void)` ...
Este é um conceito usado para obter polimorfismo na programação orientada a objetos
“Na programação de computadores, um retorno de chamada é uma referência ao código executável, ou um pedaço de código executável, que é passado como argumento para outro código. Isso permite que uma camada de software de nível inferior chame uma sub-rotina (ou função) definida em uma camada de nível superior. ” - Wikipedia
Retorno de chamada em C usando o ponteiro de função
Em C, o retorno de chamada é implementado usando o Ponteiro de Função. Ponteiro de função - como o nome sugere, é um ponteiro para uma função.
Por exemplo, int (* ptrFunc) ();
Aqui, ptrFunc é um ponteiro para uma função que não aceita argumentos e retorna um número inteiro. NÃO esqueça de colocar parênteses, caso contrário, o compilador assumirá que ptrFunc é um nome de função normal, que não aceita nada e retorna um ponteiro para um número inteiro.
Aqui está um código para demonstrar o ponteiro da função.
#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;
}
Agora vamos tentar entender o conceito de retorno de chamada em C usando o ponteiro de função.
O programa completo possui três arquivos: callback.c, reg_callback.he 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)();
}
Se rodarmos este programa, a saída será
Este é um programa que demonstra a função de retorno de chamada dentro de register_callback dentro de my_callback de volta no programa principal
A função de camada superior chama uma função de camada inferior como uma chamada normal e o mecanismo de retorno de chamada permite que a função de camada inferior chame a função de camada superior através de um ponteiro para uma função de retorno de chamada.
Retorno de chamada em Java usando a interface
Java não possui o conceito de ponteiro de função. Implementa o mecanismo de retorno de chamada através do seu mecanismo de interface. Aqui, em vez de um ponteiro de função, declaramos uma interface com um método que será chamado quando o destinatário concluir sua tarefa.
Deixe-me demonstrá-lo através de um exemplo:
A interface de retorno de chamada
public interface Callback
{
public void notify(Result result);
}
O chamador ou a classe de nível 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
}
}
A função Callee ou a camada 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
}
}
Retorno de Chamada Usando o Padrão EventListener
Esse padrão é usado para notificar de 0 a n números de Observadores / Ouvintes que uma tarefa específica foi concluída
A diferença entre o mecanismo de retorno de chamada e o mecanismo EventListener / Observer é que, no retorno de chamada, o destinatário notifica o chamador único, enquanto no Eventlisener / Observer, o destinatário pode notificar qualquer pessoa interessada nesse evento (a notificação pode ir para outras partes do aplicativo que não acionou a tarefa)
Deixe-me explicar através de um exemplo.
A interface do evento
public interface Events {
public void clickEvent();
public void longClickEvent();
}
Widget de classe
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ão Classe
public class Button extends Widget{
private String mButtonText;
public Button (){
}
public String getButtonText() {
return mButtonText;
}
public void setButtonText(String buttonText) {
this.mButtonText = buttonText;
}
}
Caixa de seleção Classe
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;
}
}
Classe de atividade
pacote 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();
}
}
Outra classe
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...");
}
}
Classe 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 você pode ver no código acima, temos uma interface chamada events que basicamente lista todos os eventos que podem acontecer para nosso aplicativo. A classe Widget é a classe base de todos os componentes da interface do usuário, como botão e caixa de seleção. Esses componentes da interface do usuário são os objetos que realmente recebem os eventos do código da estrutura. A classe Widget implementa a interface Events e também possui duas interfaces aninhadas, a saber, OnClickEventListener e OnLongClickEventListener
Essas duas interfaces são responsáveis por ouvir os eventos que podem ocorrer nos componentes da interface do usuário derivados do Widget, como Botão ou Caixa de seleção. Portanto, se compararmos este exemplo com o exemplo anterior de retorno de chamada usando a interface Java, essas duas interfaces funcionarão como a interface de retorno de chamada. Portanto, o código de nível superior (Atividade aqui) implementa essas duas interfaces. E sempre que um evento ocorrer em um widget, o código de nível superior (ou o método dessas interfaces implementadas no código de nível superior, que é aqui Atividade) será chamado.
Agora, deixe-me discutir a diferença básica entre o padrão de retorno de chamada e ouvinte de evento. Como mencionamos, usando o retorno de chamada, o Callee pode notificar apenas um único chamador. Porém, no caso do padrão EventListener, qualquer outra parte ou classe do Aplicativo pode se registrar para os eventos que podem ocorrer no Botão ou na Caixa de Seleção. O exemplo desse tipo de classe é o OtherClass. Se você vir o código da OtherClass, descobrirá que ele se registrou como ouvinte do ClickEvent que pode ocorrer no botão definido na Atividade. Parte interessante é que, além da Atividade (o chamador), essa OtherClass também será notificada sempre que o evento click ocorrer no botão.
Uma função de retorno de chamada é uma função que você passa (como referência ou ponteiro) para uma determinada função ou objeto. Essa função ou objeto chamará essa função de volta a qualquer momento mais tarde, possivelmente várias vezes, para qualquer tipo de finalidade:
...
Portanto, descrever um retorno de chamada como uma função chamada no final de outra função ou tarefa é muito simplificador (mesmo que seja um caso de uso comum).
Um retorno de chamada é uma ideia de passar uma função como parâmetro para outra função e invocá-la assim que o processo for concluído.
Se você obtiver o conceito de retorno de chamada através das respostas impressionantes acima, recomendo que você aprenda os antecedentes de sua ideia.
"O que os fez (cientistas da computação) desenvolver retorno de chamada?" Você pode aprender um problema que está bloqueando. (Especialmente o bloqueio da interface do usuário) E o retorno de chamada não é a única solução para ele. Existem muitas outras soluções (por exemplo: Thread, Futures, Promises ...).
Uma área de uso importante é que você registre uma de suas funções como identificador (ou seja, um retorno de chamada) e depois envie uma mensagem / chamada para alguma função para realizar algum trabalho ou processamento. Agora, após o término do processamento, a função chamada chamaria nossa função registrada (ou seja, agora a chamada de retorno está concluída), indicando que o processamento está concluído.
Este link da wikipedia explica muito bem graficamente.
Uma função de retorno de chamada, também conhecida como função de ordem superior, é uma função que é passada para outra função como parâmetro, e a função de retorno de chamada é chamada (ou executada) dentro da função pai.
$("#button_1").click(function() {
alert("button 1 Clicked");
});
Aqui passamos uma função como parâmetro para o método click. E o método click chamará (ou executará) a função de retorno de chamada que passamos para ele.
Função de retorno de chamada Uma função que passou para outra função como argumento.
function test_function(){
alert("Hello world");
}
setTimeout(test_function, 2000);
Nota: No exemplo acima test_function usado como argumento para a função setTimeout.