Definição da função de retorno de chamada
Uma função de retorno de chamada é uma função chamada através de um ponteiro de função. Se você passar no ponteiro (endereço) da função como um argumento para outra função, quando esse ponteiro é usado para chamar a função que aponta, dizemos que esta é uma função de retorno de chamada. A função de retorno de chamada não é chamada diretamente pelo implementador da função, mas é chamada por outra parte quando ocorre um evento ou condição específico e é usado para responder ao evento ou condição.
No JavaScript, a definição específica da função de retorno de chamada é: a função A é passada como um parâmetro (referência da função) em outra função B, e essa função B executa a função A. Digamos que a função A seja chamada de função de retorno de chamada. Se não houver nome (expressão de função), ele é chamado de função de retorno de chamada anônimo. Portanto, o retorno de chamada não é necessariamente usado para assíncrono. Os retornos de chamada são frequentemente usados em cenários gerais de síncrono (bloqueando), como exigir que algumas operações sejam executadas e a função de retorno de chamada seja executada.
exemplo
Um exemplo de uso de retornos de chamada em sincronização (bloqueio) é executar o Func2 após a execução do código Func1.
A cópia do código é a seguinte:
var func1 = function (retorno de chamada) {
// Faça algo.
(retorno de chamada && typeof (retorno de chamada) === "function") && callback ();
}
func1 (func2);
var func2 = function () {
}
Use casos de funções de retorno de chamada
Carregamento de recursos: Execute o retorno de chamada após o carregamento dinâmico de arquivos JS, execute o retorno de chamada após o carregamento do IFRAME, execute o retorno de chamada após carregar o retorno de chamada da operação do AJAX, execute retorno de chamada após carregamento da imagem, Ajax, etc.
Os eventos DOM e os eventos Node.js são baseados no mecanismo de retorno de chamada (os retornos de chamada do Node.js podem ter problemas de ninho de retorno de chamada de várias camadas).
O tempo de atraso do setTimeout é 0. Este hack é frequentemente usado. A função chamada pelo setTimeout é na verdade uma modalidade de retorno de chamada
Chamada de cadeia: Quando a chamada em cadeia, é fácil implementar a chamada de cadeia no método do avaliador (setter) (ou em métodos que não retornam valores), mas o valor getter é relativamente difícil de implementar a chamada de cadeia, porque você precisa do valor getter para retornar os dados necessários em vez desse ponteiro. Se você deseja implementar o método da cadeia, pode usar uma função de retorno de chamada para implementá -lo.
As chamadas de função do setTimeout e SetInterval obtêm seu valor de retorno. Como ambas as funções são assíncronas, ou seja, o tempo de chamada e o principal processo do programa são relativamente independentes, não há como esperar o valor de retorno no corpo, e o programa não parará e espera quando eles forem abertos, caso contrário, o significado do setTimeout e do setInterval será perdido. Portanto, não faz sentido usar o retorno, portanto, o retorno de chamada só pode ser usado. O significado do retorno de chamada é notificar a função de proxy dos resultados da execução do timer para processamento oportuno.
Funções são objetos
Se você deseja entender a função de retorno de chamada, primeiro deve entender claramente as regras da função. No JavaScript, as funções são estranhas, mas são realmente objetos. Para ser preciso, uma função é um objeto de função criado com o construtor function (). O objeto de função contém uma sequência que contém o código JavaScript da função. Se você foi transferido de C ou Java, isso pode parecer estranho, como o código poderia ser uma string? Mas para JavaScript, isso é bastante comum. A diferença entre dados e código é vaga.
A cópia do código é a seguinte:
// A função pode ser criada dessa maneira
var fn = nova função ("arg1", "arg2", "return arg1 * arg2;");
fn (2, 3); // 6
Uma vantagem disso é que você pode passar o código para outras funções ou pode passar variáveis ou objetos regulares (porque o código é literalmente apenas um objeto).
Função de transferência como retorno de chamada
É fácil passar uma função como um parâmetro.
A cópia do código é a seguinte:
função fn (arg1, arg2, retorno de chamada) {
var num = math.ceil (math.random () * (arg1 - arg2) + arg2);
retorno de chamada (num); // Passe o resultado
}
fn (10, 20, função (num) {
console.log ("retorno de chamada chamado! num:" + num);
}); // o resultado é um número aleatório entre 10 e 20
Talvez fazer isso pareça pesado e até um pouco estúpido, por que não devolver o resultado anormalmente? Mas quando você tem que usar uma função de retorno de chamada, pode não pensar assim!
Não atrapalhe
As funções tradicionais inserem os dados como parâmetros e usam as instruções de retorno para retornar valores. Em teoria, há uma declaração de retorno de retorno no final da função, que é estruturada: um ponto de entrada e um ponto de saída. Isso é mais fácil de entender. As funções estão essencialmente mapeando o processo de implementação entre entrada e saída.
No entanto, quando o processo de implementação da função for muito longo, você deve optar por aguardar a função concluir o processamento ou usar a função de retorno de chamada para executar o processamento assíncrono? Nesse caso, o uso de funções de retorno de chamada se torna crítico, como: solicitação AJAX. Se você usar uma função de retorno de chamada para processamento, o código poderá continuar executando outras tarefas sem esvaziá -lo. No desenvolvimento real, as chamadas assíncronas são frequentemente usadas em JavaScript, e é altamente recomendado aqui!
Abaixo está um exemplo mais abrangente de carregar arquivos XML usando AJAX e usar a função Call () para chamar a função de retorno de chamada no contexto do objeto solicitado.
A cópia do código é a seguinte:
função fn (url, retorno de chamada) {
var httprequest; // Crie xhr
httprequest = window.xmlhttprequest? novo xmlHttPrequest ():
window.activexObject? new ActiveXObject ("Microsoft.xmlHttp"): indefinido; // Detecção funcional para o IE
httprequest.onreadyStatechange = function () {
if (httprequest.readyState === 4
&& httprequest.status === 200) {// julgamento de status
callback.call (httprequest.Responsexml);
}
};
httprequest.open ("get", url);
httprequest.send ();
}
fn ("text.xml", function () {// chamando a função
console.log (this); // saída após esta declaração
});
console.log ("Isso será executado antes do retorno de chamada acima."); // Esta declaração é emitida primeiro
Nossos pedidos de processamento assíncrono significa que, quando começamos a solicitar, dizemos a eles para ligar para nossa função quando terminarem. Em situações reais, o manipulador de eventos ONREADESTATECHANGE também deve considerar a falha da solicitação. Aqui, assumimos que o arquivo XML existe e pode ser carregado com sucesso pelo navegador. Neste exemplo, a função assíncrona é atribuída ao evento OnreadyStateChange e, portanto, não será executado imediatamente.
Finalmente, a declaração do segundo console.log é executada primeiro, porque a função de retorno de chamada não é executada até que a solicitação seja concluída.
O exemplo acima não é fácil de entender, então dê uma olhada no exemplo a seguir:
A cópia do código é a seguinte:
function foo () {
var a = 10;
Return function () {
a *= 2;
retornar a;
};
}
var f = foo ();
f (); // retorna 20.
f (); // retorna 40.
A função é chamada externamente e ainda pode acessar a variável a. Isso é tudo porque o escopo do JavaScript é lexical. O funcional é executado no escopo que os define (o escopo dentro do exemplo no exemplo acima), e não no escopo em que essa função é executada. Enquanto F for definido no Foo, ele pode acessar todas as variáveis definidas no Foo, mesmo que a execução do Foo tenha terminado. Porque seu escopo será salvo, mas apenas a função retornada pode acessar o escopo salvo. Retornar uma função anônima incorporada é o método mais comum para criar fechamentos.