Como explicar retornos de chamada em inglês simples? Como eles são diferentes de chamar uma função de outra função?

342

Como explicar retornos de chamada em inglês simples? Como eles são diferentes de chamar uma função de outra função, tendo algum contexto da função de chamada? Como o poder deles pode ser explicado a um programador iniciante?

Yahoo-Me
fonte
11
Acredito que o nome científico disso seja estilo de passagem contínua. Você pode procurar por isso no wiki.
11333 ming_codes #
11
Há algumas boas respostas para uma questão idêntica no Quora também
DBR
A melhor explicação sobre retorno de chamada que eu já encontrei youtube.com/watch?v=xHneyv38Jro
Sameer Sinha

Respostas:

114

Freqüentemente, um aplicativo precisa executar diferentes funções com base em seu contexto / estado. Para isso, usamos uma variável na qual armazenamos as informações sobre a função a ser chamada. De acordo com sua necessidade, o aplicativo definirá essa variável com as informações sobre a função a ser chamada e chamará a função usando a mesma variável.

Em javascript, o exemplo está abaixo. Aqui usamos o argumento do método como uma variável em que armazenamos informações sobre a função.

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
fonte
18
Enquanto isso é tecnicamente um retorno de chamada, a explicação dada soa indistinta de um ponteiro de função geral. Seria útil incluir algumas justificativas para o uso de um retorno de chamada.
Eric
4
Eu não entendo essa resposta. Pode ser mais uma explicação do que o código?
Abhishek Singh
porque nos nao podemos fazer o que fazemos na função de chamada de retorno (a function(arg)) na processArray(arr,callback)função
Abhi
11
@ JoSmo, você está parcialmente correto. Passe uma variável + função de retorno de chamada como parâmetros, obtendo o resultado criado com a variável pela função original e passe-o na função de retorno de chamada para processamento adicional. exemplo: func1 (a, callback_func) {v = a + 1} e existe uma função predefinida de retorno de chamada: callback_func (v) {return v + 1;} isso aumentará a em 2, portanto, se você passar o argumento do número inteiro 4 em "a", o callback_funct retornará 6 como resultado. Leia esta melhor fonte que eu encontrei na callbackhell.com .
Dung
Esta resposta não é clara. Poderia ser mais simples e articulado!
Arjun Kalidas
545

Vou tentar manter esse morto simples. Um "retorno de chamada" é qualquer função chamada por outra função que aceita a primeira função como parâmetro. Na maioria das vezes, um "retorno de chamada" é uma função que é chamada quando algo acontece. Que algo pode ser chamado de "evento" na fala do programador.

Imagine este cenário: você está esperando um pacote em alguns dias. O pacote é um presente para o seu vizinho. Portanto, uma vez que você obtém o pacote, deseja que ele seja trazido para os vizinhos. Você está fora da cidade e deixa instruções para seu cônjuge.

Você poderia dizer a eles para pegar o pacote e levá-lo aos vizinhos. Se o seu cônjuge fosse tão estúpido quanto um computador, eles se sentariam à porta e esperariam o pacote até ele chegar (NÃO FAZENDO ALGO MAIS) e, depois que chegassem, o levariam aos vizinhos. Mas há uma maneira melhor. Diga ao seu cônjuge que, uma vez que receberem o pacote, eles deverão trazê-lo para os vizinhos. Então, eles podem seguir a vida normalmente até receberem o pacote.

Em nosso exemplo, o recebimento do pacote é o "evento" e o envio para os vizinhos é o "retorno de chamada". Seu cônjuge "executa" suas instruções para trazer o pacote somente quando o pacote chegar. Muito melhor!

Esse tipo de pensamento é óbvio na vida cotidiana, mas os computadores não têm o mesmo tipo de bom senso. Considere como os programadores normalmente gravam em um arquivo:

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

Aqui, esperamos que o arquivo seja aberto antes de escrever nele. Isso "bloqueia" o fluxo de execução e nosso programa não pode fazer nenhuma das outras coisas que possa precisar! E se pudéssemos fazer isso:

# 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!

Acontece que fazemos isso com algumas linguagens e estruturas. É muito legal! Confira o Node.js para obter algumas práticas reais com esse tipo de pensamento.

Josh Imhoff
fonte
6
Isso está correto, mas não abrange todos os casos de uso comuns para retornos de chamada. Geralmente, você usa retornos de chamada quando precisa chamar uma função com argumentos que seriam processados ​​no processo de outra função. Por exemplo, no PHP array_filter () e array_map (), os retornos de chamada são chamados em um loop.
Haralan Dobrev 13/03/2012
2
O exemplo do arquivo de gravação é apropriado? Parece fazer suposições sobre como openfunciona. É plausível que openpossa bloquear internamente enquanto aguarda o sistema operacional fazer sua magia negra, na qual o retorno de chamada é executado. Não há diferença no resultado nesse caso.
13139 Kenneth K.
23
Boa explicação, mas estou um pouco confuso. O retorno de chamada é multithread?
Premraj
11
Ótimo exemplo! Estava à procura de tudo Inglês plain todo o lugar e este é o primeiro que eu encontrei até agora :)
ChristoKiwi
11
O que torna a função aberta no seu exemplo sem bloqueio? aberto ainda podem bloquear o fluxo de execução ..
Koray Tugay
82

Como explicar retornos de chamada em inglês simples?

Em inglês simples, uma função de retorno de chamada é como um Trabalhador que "liga de volta" para seu Gerente quando ele conclui uma Tarefa .

Como eles são diferentes de chamar uma função de outra função, tendo algum contexto da função de chamada?

É verdade que você está chamando uma função de outra função, mas a chave é que o retorno de chamada é tratado como um Objeto, para que você possa alterar qual Função chamar com base no estado do sistema (como o Padrão de Design da Estratégia).

Como o poder deles pode ser explicado a um programador iniciante?

O poder dos retornos de chamada pode ser facilmente visto em sites no estilo AJAX, que precisam extrair dados de um servidor. O download dos novos dados pode levar algum tempo. Sem retornos de chamada, toda a interface do usuário "congelaria" durante o download dos novos dados ou você precisaria atualizar a página inteira em vez de apenas parte dela. Com um retorno de chamada, você pode inserir uma imagem "now loading" e substituí-la pelos novos dados depois de carregados.

Algum código sem retorno de chamada:

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)');
}

Com retorno de chamada:

Aqui está um exemplo com um retorno de chamada, usando getJSON do 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
}

Com fechamento:

Freqüentemente, o retorno de chamada precisa acessar stateda função de chamada usando a closure, que é como o Trabalhador que precisa obter informações do Gerente antes que ele possa concluir sua Tarefa . Para criar o closure, você pode incorporar a função para que ela veja os dados no contexto de chamada:

/* 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); 

Fecho

Finalmente, aqui está uma definição de closurede Douglas Crockford :

As funções podem ser definidas dentro de outras funções. A função interna tem acesso aos vars e aos parâmetros da função externa. Se uma referência a uma função interna sobreviver (por exemplo, como uma função de retorno de chamada), os vars da função externa também sobreviverão.

Veja também:

user508994
fonte
12
+1. O primeiro parágrafo é estrondo no dinheiro . No entanto, o restante entra no jargão da ciência da computação muito rapidamente.
TarkaDaal
41

Fico surpreso ao ver tantas pessoas inteligentes falhando em enfatizar a realidade que a palavra "retorno de chamada" passou a ser usada de duas maneiras inconsistentes.

Ambas as formas envolvem a personalização de uma função passando funcionalidade adicional (uma definição de função, anônima ou nomeada) para uma função existente. ie

customizableFunc(customFunctionality)

Se a funcionalidade personalizada estiver simplesmente conectada ao bloco de código, você personalizou a função, assim.

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

Embora esse tipo de funcionalidade injetada seja freqüentemente chamado de "retorno de chamada", não há nada contingente. Um exemplo muito óbvio é o método forEach, no qual uma função personalizada é fornecida como um argumento a ser aplicado a cada elemento em uma matriz para modificar a matriz.

Mas isso é fundamentalmente distinto do uso de funções de "retorno de chamada" para programação assíncrona , como no AJAX ou node.js ou simplesmente na atribuição de funcionalidade a eventos de interação do usuário (como cliques do mouse). Nesse caso, a idéia é aguardar a ocorrência de um evento contingente antes de executar a funcionalidade customizada. Isso é óbvio no caso da interação do usuário, mas também é importante nos processos de E / S (entrada / saída) que podem levar tempo, como a leitura de arquivos do disco. É aqui que o termo "retorno de chamada" faz o sentido mais óbvio. Depois que um processo de E / S é iniciado (como solicitar que um arquivo seja lido do disco ou de um servidor para retornar dados de uma solicitação http), é assíncronaprograma não espera para terminar. Ele pode prosseguir com as tarefas agendadas a seguir e responder apenas com a funcionalidade personalizada após ter sido notificado de que o arquivo de leitura ou a solicitação http foi concluída (ou que falhou) e que os dados estão disponíveis para a funcionalidade personalizada. É como ligar para uma empresa por telefone e deixar seu número de "retorno de chamada", para que eles possam ligar quando alguém estiver disponível para entrar em contato com você. É melhor do que ficar na fila para quem sabe quanto tempo e não poder atender a outros assuntos.

O uso assíncrono envolve inerentemente alguns meios de escutar o evento desejado (por exemplo, a conclusão do processo de E / S) para que, quando ele ocorra (e somente quando ele ocorra), a funcionalidade "retorno de chamada" personalizada seja executada. No exemplo óbvio do AJAX, quando os dados realmente chegam do servidor, a função "retorno de chamada" é acionada para usar esses dados para modificar o DOM e, portanto, redesenhar a janela do navegador nessa extensão.

Para recapitular. Algumas pessoas usam a palavra "retorno de chamada" para se referir a qualquer tipo de funcionalidade personalizada que pode ser injetada em uma função existente como argumento. Mas, pelo menos para mim, o uso mais apropriado da palavra é onde a função "retorno de chamada" injetada é usada de forma assíncrona - para ser executada somente na ocorrência de um evento que está aguardando para ser notificado.

Robert Polevoi
fonte
Então, quando a função retorna, para onde retorna o processo? Por exemplo, se houver quatro linhas de código; 1.fileObject = aberto (arquivo, writeToFile); 2. doSomething1 (); 3. doSomething2 (); 4. doSomething3 ().
MagicLAMP 10/10
A linha 1 é executada, mas em vez de aguardar a abertura do arquivo, prossegue para a linha 2 e, em seguida, 3. Nesse ponto, o arquivo é aberto e (quando a linha 3 termina qualquer operação de semáforo) retorna para o contador do programa para dizer " passe o controle para writeToFile "que faz as coisas e, quando terminar, passe o controle de volta ao ponto em que a INT ocorreu na linha 3 ou na linha 4 se a linha 3 tiver que terminar.
MagicLAMP 10/10
11
Esta é uma explicação muito articulada de outro ponto importante: por exemplo, a diferença entre a função passada como um argumento para Array.prototype.forEach()e a função passada como um argumento para setTimeout(), e eles são cavalos de cores diferentes, na medida em que você pensa sobre seu programa .
Mckmcneil 23/10/2015
26

Em termos não programadores, um retorno de chamada é um preenchimento em branco em um programa.

Um item comum em muitos formulários em papel é "Pessoa para ligar em caso de emergência". Há uma linha em branco lá. Você escreve o nome e o número de telefone de alguém. Se ocorrer uma emergência, essa pessoa será chamada.

  • Todo mundo recebe o mesmo formulário em branco, mas
  • Todos podem escrever um número de contato de emergência diferente.

Isso é fundamental. Você não altera o formulário (o código, geralmente o de outra pessoa). No entanto, você pode preencher as informações que faltam ( seu número).

Exemplo 1:

Os retornos de chamada são usados ​​como métodos personalizados, possivelmente para adicionar / alterar o comportamento de um programa. Por exemplo, pegue um código C que executa uma função, mas não sabe como imprimir a saída. Tudo o que pode fazer é criar uma string. Quando tenta descobrir o que fazer com a string, vê uma linha em branco. Mas, o programador deu a você o espaço em branco para escrever sua chamada de retorno!

Neste exemplo, você não use um lápis para preencher um espaço em branco em uma folha de papel, você usa a função set_print_callback(the_callback).

  • A variável em branco no módulo / código é a linha em branco,
  • set_print_callback é o lápis
  • e the_callbacké sua informação que você está preenchendo.

Agora você preencheu esta linha em branco no programa. Sempre que precisar imprimir a saída, ela olhará para essa linha em branco e seguirá as instruções (ex: chamar a função que você coloca lá). Praticamente, isso permite a possibilidade de imprimir na tela, em um arquivo de log, em uma impressora, através de uma conexão de rede ou qualquer combinação deles. Você preencheu o espaço em branco com o que deseja fazer.

Exemplo 2:

Quando lhe dizem que precisa ligar para um número de emergência, você lê o que está escrito no formulário em papel e liga para o número que lê. Se essa linha estiver em branco, nada será feito.

A programação da GUI funciona da mesma maneira. Quando um botão é clicado, o programa precisa descobrir o que fazer a seguir. Ele vai e procura o retorno de chamada. Esse retorno de chamada acontece em um espaço em branco rotulado "Aqui está o que você faz quando o Botão1 é clicado"

A maioria dos IDEs preencherá automaticamente o espaço em branco para você (escreva o método básico) quando você solicitar (por exemplo button1_clicked). No entanto, esse espaço em branco pode ter qualquer método que você queira, por favor . Você pode chamar o método run_computationsou butter_the_biscuitsdesde que coloque o nome do retorno de chamada no espaço em branco apropriado. Você pode colocar "555-555-1212" no número de emergência em branco. Não faz muito sentido, mas é permitido.


Nota final: a linha em branco que você está preenchendo com o retorno de chamada? Pode ser apagado e reescrito à vontade. (se você deve ou não é outra questão, mas isso faz parte do poder deles)

JoeyG
fonte
21

Sempre melhor começar com um exemplo :).

Vamos supor que você tenha dois módulos A e B.

Você deseja que o módulo A seja notificado quando ocorrer algum evento / condição no módulo B. No entanto, o módulo B não tem idéia do seu módulo A. Tudo o que sabe é um endereço para uma função específica (do módulo A) por meio de um ponteiro de função. fornecido pelo módulo A.

Portanto, tudo o que B precisa fazer agora é "retorno de chamada" no módulo A quando um evento / condição específico ocorre usando o ponteiro de função. A pode fazer um processamento adicional dentro da função de retorno de chamada.

*) Uma vantagem clara aqui é que você está abstraindo tudo sobre o módulo A do módulo B. O módulo B não precisa se preocupar com quem / o módulo A.

Gargi Srinivas
fonte
Portanto, os parâmetros para a função em A são fornecidos no módulo B, estão corretos?
U.Savas 21/04
21

Johny, o programador, precisa de um grampeador, então ele vai até o departamento de suprimentos de escritório e pede um. Depois de preencher o formulário de solicitação, ele pode ficar parado ali e esperar o atendente ir procurar o grampeador no armazém (como uma chamada de função de bloqueio ) ou vá fazer outra coisa enquanto isso.

como isso geralmente leva tempo, johny coloca uma nota junto com o formulário de solicitação, solicitando que liguem para ele quando o grampeador estiver pronto para a coleta, portanto, enquanto isso, ele pode fazer outra coisa como cochilar em sua mesa.

tovmeod
fonte
11
Isso parece um pouco mais parecido com promessas do que com retornos de chamada: blog.jcoglan.com/2013/03/30/…
Thomas
2
Promessas são apenas açúcar sintático em torno de retornos de chamada.
precisa saber é o seguinte
20

Imagine que você precisa de uma função que retorne 10 ao quadrado para escrever uma função:

function tenSquared() {return 10*10;}

Mais tarde, você precisa de 9 ao quadrado para escrever outra função:

function nineSquared() {return 9*9;}

Eventualmente, você substituirá tudo isso por uma função genérica:

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

O mesmo pensamento se aplica aos retornos de chamada. Você tem uma função que faz alguma coisa e, quando concluída, chama doA:

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

Mais tarde, você deseja a mesma função exata para chamar doB, em vez disso, poderá duplicar toda a função:

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

Ou você pode passar uma função de retorno de chamada como uma variável e só precisa ter a função uma vez:

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

Então você só precisa chamar computação (doA) e computação (doB).

Além de simplificar o código, ele permite que o código assíncrono saiba que ele foi concluído ao chamar sua função arbitrária na conclusão, semelhante a quando você liga para alguém no telefone e deixa um número de retorno de chamada.

Brian Nickel
fonte
Então você está passando a função como parâmetro. Toda linguagem de programação permite a passagem de função como parâmetro? Se não, você pode mostrar um exemplo de como implementar a função de retorno de chamada nesse idioma.
Quazi Irfan
11

Você se sente mal e vai ao médico. Ele examina você e determina que você precisa de algum medicamento. Ele prescreve alguns remédios e chama a receita na sua farmácia local. Você vai para casa. Mais tarde, sua farmácia liga para informar que sua prescrição está pronta. Você vai buscá-lo.

efígie
fonte
Muito boa analogia. Você poderia expandir um pouco mais, talvez com alguns exemplos (simples) relacionados à programação?
a20 4/04
10

Há dois pontos a serem explicados: um é como um retorno de chamada funciona (passando uma função que pode ser chamada sem nenhum conhecimento de seu contexto), o outro para o qual é usado (manipulando eventos de forma assíncrona).

A analogia de esperar a chegada de um pacote que tenha sido usado por outras respostas é boa para explicar as duas coisas. Em um programa de computador, você diria ao computador para esperar uma parcela. Normalmente, ele ficava ali sentado e aguardava (e não fazia mais nada) até que o pacote chegasse, possivelmente indefinidamente, se nunca chegar. Para os humanos, isso parece bobagem, mas sem outras medidas, isso é totalmente natural para um computador.

Agora a chamada seria a campainha na sua porta da frente. Você fornece ao serviço de encomendas uma maneira de notificá-lo da chegada da encomenda sem que eles precisem saber onde (mesmo se) você está na casa ou como a campainha funciona. (Por exemplo, alguns "sinos" realmente enviam uma ligação). Como você forneceu uma "função de retorno de chamada" que pode ser "chamada" a qualquer momento, fora do contexto, agora você pode parar de sentar na varanda da frente e "lidar com o evento "(de chegada de encomendas) sempre que for a hora.

Hanno Fietz
fonte
Isso é inglês simples.
Jeb50
Esta parece ser a melhor explicação!
Vishal Sharma
6

Imagine que uma amiga está saindo de sua casa e você diz a ela "Me ligue quando chegar em casa para que eu saiba que você chegou em segurança"; isso é (literalmente) uma ligação de volta . É isso que é uma função de retorno de chamada, independentemente do idioma. Você deseja que algum procedimento repasse o controle para você quando concluir alguma tarefa, portanto, você atribui a ele uma função para chamá-lo.

Em Python, por exemplo,

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

grabDBValuepode ser gravado para pegar apenas um valor de um banco de dados e permitir que você especifique o que realmente fazer com o valor, para que ele aceite uma função. Você não sabe quando ou se grabDBValueretornará, mas se / quando ocorrer, você sabe o que deseja que faça. Aqui, passo uma função anônima (ou lambda ) que envia o valor para uma janela da GUI. Eu poderia facilmente mudar o comportamento do programa fazendo o seguinte:

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

Os retornos de chamada funcionam bem em idiomas onde as funções são valores de primeira classe , assim como os números inteiros usuais, cadeias de caracteres, booleanos, etc. em Java, o chamador solicitará uma classe estática de um determinado tipo com um determinado nome de método, pois não há funções ("métodos", realmente) fora das classes; e na maioria das outras linguagens dinâmicas, você pode simplesmente passar uma função com sintaxe simples.

Protip:

Em idiomas com escopo lexical (como Scheme ou Perl), você pode fazer um truque 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

$valnesse caso, será 6porque o retorno de chamada tem acesso às variáveis ​​declaradas no ambiente lexical em que foi definido. O escopo lexical e as chamadas de retorno anônimas são uma combinação poderosa que requer mais estudos para o programador iniciante.

gatlin
fonte
11
+1. Na verdade, eu gosto bastante dessa resposta. A explicação do que uma chamada de retorno é , é simples e concisa.
TarkaDaal
6

Você tem algum código que deseja executar. Normalmente, quando você o chama, espera que ele termine antes de continuar (o que pode fazer com que seu aplicativo fique cinza / produza um tempo de rotação para um cursor).

Um método alternativo é executar esse código em paralelo e continuar com seu próprio trabalho. Mas e se o seu código original precisar fazer coisas diferentes, dependendo da resposta do código que chamou? Bem, nesse caso, você pode passar o nome / local do código que deseja chamar quando terminar. Este é um "retorno de chamada".

Código normal: Peça Informações-> Informações do Processo-> Lide com os resultados do Processamento-> Continue fazendo outras coisas.

Com retornos de chamada: Solicite informações-> Informações do processo-> Continue fazendo outras coisas. E em algum momento posterior-> Lide com os resultados do processamento.

Andrew Ducker
fonte
6

Sem retorno de chamada nem outros recursos especiais de programação (como threading e outros), um programa é exatamente uma sequência de instruções executadas seqüencialmente uma após a outra , e mesmo com um tipo de "comportamento dinâmico" determinado por determinadas condições, todos os cenários possíveis deve ser previamente programado .

Portanto, se precisarmos fornecer um comportamento dinâmico real a um programa, podemos usar o retorno de chamada. Com o retorno de chamada, você pode instruir por parâmetros, um programa para chamar outro programa, fornecendo alguns parâmetros definidos anteriormente e esperar alguns resultados ( esta é a assinatura do contrato ou da operação ), para que esses resultados possam ser produzidos / processados ​​por um programa de terceiros que não foi não era conhecido anteriormente.

Essa técnica é a base do polimorfismo aplicado a programas, funções, objetos e todas as outras unidades de código executadas por computadores.

O mundo humano usado como exemplo para retorno de chamada é bem explicado quando você está fazendo algum trabalho, vamos supor que você seja um pintor ( aqui você é o programa principal, que pinta ) e, às vezes, ligue para o seu cliente para pedir que ele aprove o resultado do seu trabalho , ele decide se a imagem é boa ( seu cliente é o programa de terceiros ).

No exemplo acima, você é um pintor e "delega" a outros o trabalho para aprovar o resultado, a imagem é o parâmetro e cada novo cliente (a "função" chamada de retorno) altera o resultado do seu trabalho, decidindo o que ele deseja sobre a imagem ( a decisão tomada pelos clientes é o resultado retornado da "função de retorno de chamada" ).

Espero que esta explicação possa ser útil.

Luciano
fonte
6

Vamos fingir que você deveria me dar uma tarefa potencialmente demorada: obter os nomes das cinco primeiras pessoas únicas que você se deparar. Isso pode levar dias se eu estiver em uma área escassamente povoada. Você não está realmente interessado em ficar sentado em suas mãos enquanto eu corro por aí, então você diz: "Quando tiver a lista, ligue para meu celular e leia de novo para mim. Aqui está o número".

Você me forneceu uma referência de retorno de chamada - uma função que devo executar para entregar mais processamento.

Em JavaScript, pode ser algo como isto:

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);

Provavelmente isso poderia ser melhorado de várias maneiras. Por exemplo, você pode fornecer um segundo retorno de chamada: se demorar mais de uma hora, ligue para o telefone vermelho e diga à pessoa que responde que você atingiu o tempo limite.

steamer25
fonte
6

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 ++"

DejanLekic
fonte
Uma explicação mais fácil seria: ligo para alguém, ela está em uma reunião, deixo um número de telefone, ela liga de volta.
Solitário
5

Um retorno de chamada é uma função que será chamada por uma segunda função. Esta segunda função não sabe de antemão qual função chamará. Portanto, a identidade da função de retorno de chamada é armazenada em algum lugar ou transmitida para a segunda função como parâmetro. Essa "identidade", dependendo da linguagem de programação, pode ser o endereço do retorno de chamada ou algum outro tipo de ponteiro, ou pode ser o nome da função. O principal é o mesmo, armazenamos ou passamos algumas informações que identificam inequivocamente a função.

Quando chegar a hora, a segunda função pode chamar o retorno de chamada, fornecendo parâmetros dependendo das circunstâncias naquele momento. Pode até escolher o retorno de chamada entre um conjunto de possíveis retornos de chamada. A linguagem de programação deve fornecer algum tipo de sintaxe para permitir que a segunda função chame o retorno de chamada, conhecendo sua "identidade".

Esse mecanismo tem muitos usos possíveis. Com os retornos de chamada, o designer de uma função pode permitir que ela seja personalizada fazendo com que ela chame os retornos de chamada fornecidos. Por exemplo, uma função de classificação pode usar um retorno de chamada como parâmetro, e esse retorno de chamada pode ser uma função para comparar dois elementos para decidir qual deles vem primeiro.

A propósito, dependendo da linguagem de programação, a palavra "função" na discussão acima pode ser substituída por "bloco", "encerramento", "lambda" etc.

David Casseres
fonte
5

Normalmente enviamos variáveis ​​para funções. Suponha que você tenha uma tarefa em que a variável precisa ser processada antes de ser fornecida como argumento - você pode usar o retorno de chamada.

function1(var1, var2) é o caminho usual.

E se eu quiser var2ser processado e depois enviado como argumento? function1(var1, function2(var2))

Este é um tipo de retorno de chamada - onde function2executa algum código e retorna uma variável de volta à função inicial.

Nishant
fonte
2
Qual é outro tipo de retorno de chamada?
johnny
@johnny: Existem retornos de chamada normais do navegador que são acionados quando um Ajax é concluído etc.
Nishant
4

Uma explicação metafórica:

Tenho uma encomenda que quero entregar a um amigo e também quero saber quando meu amigo a recebe.

Então, levo o pacote para os correios e peço que entreguem. Se eu quiser saber quando meu amigo recebe o pacote, tenho duas opções:

(a) Posso esperar nos correios até que seja entregue.

(b) Receberei um email quando ele for entregue.

A opção (b) é análoga a um retorno de chamada.

tonylo
fonte
4

Para ensinar retornos de chamada, você deve ensinar o ponteiro primeiro. Depois que os alunos entenderem a idéia de apontar para uma variável, a idéia de retornos de chamada ficará mais fácil. Supondo que você esteja usando C / C ++, essas etapas podem ser seguidas.

  • Primeiro, mostre aos seus alunos como usar e manipular variáveis ​​usando ponteiros e usando os identificadores de variáveis ​​normais.
  • Depois, ensine a eles que há coisas que só podem ser feitas com ponteiros (como passar uma variável por referência).
  • Diga-lhes como o código ou as funções executáveis ​​são como outros dados (ou variáveis) na memória. Portanto, as funções também têm endereços ou ponteiros.
  • Em seguida, mostre a eles como as funções podem ser chamadas com ponteiros de função e diga que são chamadas de retorno de chamada.
  • Agora, a pergunta é: por que todos esses problemas para chamar algumas funções? Qual o benefício? Como ponteiros de dados, o ponteiro de função, também conhecido como retorno de chamada, tem algumas vantagens em relação ao uso de identificadores normais.
  • O primeiro é que os identificadores ou nomes de funções não podem ser usados ​​como dados normais. Quero dizer, você não pode criar uma estrutura de dados com funções (como uma matriz ou uma lista vinculada de funções). Mas com retornos de chamada, você pode criar uma matriz, uma lista vinculada ou usá-los com outros dados, como no dicionário de pares ou árvores de valor-chave ou qualquer outra coisa. Este é um benefício poderoso. E outros benefícios são realmente filhos deste.
  • O uso mais comum de retornos de chamada é visto na programação do driver de evento. Onde uma ou mais funções são executadas com base em algum sinal de entrada. Com retornos de chamada, um dicionário pode ser mantido para mapear sinais com retornos de chamada. Então, a resolução do sinal de entrada e a execução do código correspondente se tornam muito mais fáceis.
  • O segundo uso de retornos de chamada que vem à minha mente são funções de ordem superior. As funções que assumem outras funções como argumentos de entrada. E para enviar funções como argumentos, precisamos de retornos de chamada. Um exemplo pode ser uma função que recebe uma matriz e um retorno de chamada. Em seguida, ele executa o retorno de chamada em cada um dos itens da matriz e retorna os resultados em outra matriz. Se passarmos à função um retorno de chamada duplicado, obteremos uma matriz com valor duplicado. Se passarmos um retorno de chamada quadrado, obteremos quadrados. Para raízes quadradas, basta enviar um retorno de chamada apropriado. Isso não pode ser feito com funções normais.

Pode haver muito mais coisas. Envolva os alunos e eles descobrirão. Espero que isto ajude.

Gulshan
fonte
11
Minha outra resposta relacionadas a este tópico em programmers.SE programmers.stackexchange.com/a/75449/963
Gulshan
3

Em inglês simples, um retorno de chamada é uma promessa. Joe, Jane, David e Samantha compartilham uma carona para trabalhar. Joe está dirigindo hoje. Jane, David e Samantha têm algumas opções:

  1. Verifique a janela a cada 5 minutos para ver se Joe está fora
  2. Continue fazendo o trabalho deles até Joe tocar a campainha da porta.

Opção 1: É mais como um exemplo de pesquisa em que Jane ficaria presa em um "loop", verificando se Joe estava do lado de fora. Jane não pode fazer mais nada nesse meio tempo.

Opção 2: este é o exemplo de retorno de chamada. Jane diz a Joe para tocar a campainha quando ele está do lado de fora. Ela lhe dá uma "função" para tocar a campainha da porta. Joe não precisa saber como a campainha da porta funciona ou onde ela está, ele só precisa chamar essa função, ou seja, tocar a campainha da porta quando estiver lá.

Os retornos de chamada são direcionados por "eventos". Neste exemplo, o "evento" é a chegada de Joe. No Ajax, por exemplo, os eventos podem ser "sucesso" ou "falha" da solicitação assíncrona e cada um pode ter o mesmo ou diferentes retornos de chamada.

Em termos de aplicativos JavaScript e retornos de chamada. Também precisamos entender "fechamentos" e o contexto do aplicativo. O que "isso" se refere pode facilmente confundir os desenvolvedores de JavaScript. Neste exemplo, dentro do método / retorno de chamada "ring_the_door_bell ()" de cada pessoa, pode haver outros métodos que cada pessoa precisa executar com base na rotina matinal ex. "desligue a televisão()". Queremos que "this" se refira ao objeto "Jane" ou ao objeto "David", para que cada um possa configurar o que mais precisar antes de Joe buscá-los. É aqui que a configuração do retorno de chamada com Joe exige a paródia do método, para que "this" se refira ao objeto correto.

Espero que ajude!

Nael El Shawwa
fonte
3

Um retorno de chamada é um envelope carimbado auto-endereçado. Quando você chama uma função, é como enviar uma carta. Se você deseja que essa função chame outra função, forneça essas informações na forma de uma referência ou endereço.

pete
fonte
3

Eu acho que é uma tarefa bastante fácil de explicar.

No primeiro retorno de chamada, são apenas funções comuns.
E, além disso, chamamos essa função (vamos chamá-la de A) de dentro de outra função (vamos chamá-la de B).

A mágica disso é que eu decido qual função deve ser chamada pela função de fora de B.

No momento em que escrevo a função BI, não sei qual função de retorno de chamada deve ser chamada. No momento em que chamo a função BI, também digo a essa função para chamar a função A. Isso é tudo.

yunzen
fonte
3

O que é uma função de retorno de chamada?

A resposta simples para essa primeira 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.

É difícil rastrear a função de retorno de chamada, mas às vezes é muito útil. Especialmente quando você está projetando bibliotecas. A função de retorno de chamada é como pedir ao usuário que lhe forneça um nome de função e você a chamará sob determinada condição.

Por exemplo, você escreve um cronômetro de retorno de chamada. Permite especificar a duração e qual função chamar, e a função será retornada de acordo. “Execute myfunction () a cada 10 segundos por 5 vezes”

Ou você pode criar um diretório de funções, passando uma lista do nome da função e solicitar à biblioteca que retorne a chamada adequadamente. "Sucesso de retorno de chamada () se for bem-sucedido, falha de retorno de chamada () se falhou."

Vamos ver um exemplo simples de ponteiro de função

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

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

Como passar o argumento para a função de retorno de chamada?

Observado que o ponteiro de função para implementar retorno de chamada recebe nulo *, o que indica que ele pode receber qualquer tipo de variável, incluindo estrutura. Portanto, você pode passar vários argumentos por estrutura.

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
fonte
2

Um retorno de chamada é um método que está programado para ser executado quando uma condição for atendida.

Um exemplo do "mundo real" é uma loja de videogame local. Você está esperando o Half-Life 3. Em vez de ir à loja todos os dias para ver se está, você registra seu email em uma lista para ser notificado quando o jogo estiver disponível. O email se torna seu "retorno de chamada" e a condição a ser atendida é a disponibilidade do jogo.

Um exemplo de "programadores" é uma página da web em que você deseja executar uma ação quando um botão é clicado. Você registra um método de retorno de chamada para um botão e continua executando outras tarefas. Quando / se o usuário clicar no botão, o navegador examinará a lista de retornos de chamada para esse evento e chamará seu método.

Um retorno de chamada é uma maneira de manipular eventos de forma assíncrona. Você nunca pode saber quando o retorno de chamada será executado ou se será executado. A vantagem é que ele libera seu programa e ciclos de CPU para executar outras tarefas enquanto aguarda a resposta.

Otimista
fonte
Dizer que está "agendado" pode causar confusão aqui. Os retornos de chamada são frequentemente usados ​​em sistemas assíncronos e não haveria um "agendamento", mas um "evento" que aciona o retorno de chamada a ser executado.
precisa saber é o seguinte
2

Puro e simples: um retorno de chamada é uma função que você atribui a outra função, para que possa chamá- lo.

Geralmente é chamado quando alguma operação é concluída. Como você cria o retorno de chamada antes de entregá-lo à outra função, é possível inicializá-lo com informações de contexto do site de chamada. É por isso que é chamada de chamada * back * - a primeira função chama de volta ao contexto de onde foi chamada.

Andrei Vajna II
fonte
2

“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

  • Item da lista

Esse padrão é usado para notificar de 0 a n números de Observadores / Ouvintes que uma tarefa específica foi concluída

  • Item da lista

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 de 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.

somenath mukhopadhyay
fonte
1

Os retornos de chamada permitem que você insira seu próprio código em outro bloco de código a ser executado em outro momento, que modifica ou adiciona ao comportamento desse outro bloco de código para atender às suas necessidades. Você ganha flexibilidade e capacidade de personalização enquanto pode ter um código mais sustentável.

Menos código rígido = mais fácil de manter e alterar = menos tempo = mais valor comercial = grandiosidade.

Por exemplo, em javascript, usando Underscore.js, você pode encontrar todos os elementos pares em uma matriz como esta:

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

Exemplo cortesia de Underscore.js: http://documentcloud.github.com/underscore/#filter

letuboy
fonte
1

[editado] quando temos duas funções, digamos functionA e functionB , se functionA depende da funçãoB .

então chamamos functionB como uma função de retorno de chamada . isso é amplamente usado no framework Spring.

exemplo de função de retorno de chamada da Wikipedia

Balaswamy Vaddeman
fonte
1

Pense em um método como dar uma tarefa a um colega de trabalho. Uma tarefa simples pode ser a seguinte:

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

Seu colega de trabalho faz as contas diligentemente e fornece o seguinte resultado:

x = -6
y = -4

Mas seu colega de trabalho tem um problema, ele nem sempre entende as notações, como ^, mas ele as entende pela descrição. Tais como exponent. Toda vez que ele encontra um desses, você recebe de volta o seguinte:

I don't understand "^"

Isso exige que você reescreva todo o conjunto de instruções novamente depois de explicar o que o personagem significa para o seu colega de trabalho, e ele nem sempre se lembra entre as perguntas. E ele também tem dificuldade em se lembrar das suas dicas, como é o caso de me perguntar. Ele sempre segue suas instruções escritas da melhor maneira possível.

Você pensa em uma solução, basta adicionar o seguinte a todas as suas instruções:

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

Agora, sempre que ele tem um problema, ele liga e pergunta, em vez de dar uma resposta ruim e reiniciar o processo.

Guvante
fonte
0

Isso em termos de download de uma página da web:

Seu programa é executado em um telefone celular e está solicitando a página da web http://www.google.com . Se você escrever seu programa de forma síncrona, a função que você escreve para baixar os dados estará em execução contínua até que todos os dados sejam baixados. Isso significa que sua interface do usuário não será atualizada e basicamente parecerá congelada. Se você escreve seu programa usando retornos de chamada, solicita os dados e diz "execute esta função quando terminar". Isso permite que a interface do usuário ainda permita a interação do usuário durante o download do arquivo. Após o download da página, sua função de resultado (retorno de chamada) é chamada e você pode manipular os dados.

Basicamente, ele permite que você solicite algo e continue executando enquanto aguarda o resultado. Depois que o resultado voltar para você por meio de uma função de retorno de chamada, você poderá retomar a operação de onde parou.

sokket
fonte