Como você deve saber, o ambiente de execução da linguagem JavaScript é "Thread Single Thread".
O chamado "Thread" significa que uma tarefa só pode ser concluída por vez. Se houver várias tarefas, você deverá fazer fila, concluir a tarefa anterior, executar a próxima tarefa e assim por diante.
A vantagem desse modelo é que ele é relativamente simples de implementar e o ambiente de execução é relativamente simples; execução de todo o programa. Os navegadores comuns não respondem (morte falsa) frequentemente porque uma certa peça de código JavaScript é executada por um longo tempo (como um loop morto), fazendo com que a página inteira fique presa neste local e outras tarefas não podem ser executadas.
Para resolver esse problema, o idioma JavaScript divide o modo de execução de tarefas em dois tipos: síncrono (síncrono) e assíncrono (assíncrono).
"Modo síncrono" é o modo da seção anterior, e a última tarefa aguarda que a tarefa anterior termine e a executa Completamente diferente, e cada tarefa é uma ou mais funções de retorno de chamada (retornos de chamada). Para terminar, a ordem de execução do programa é e a tarefa.
"Modo assíncrono" é muito importante. No lado do navegador, as operações de longo prazo devem ser executadas de forma assíncrona para evitar que o navegador perca a resposta. No lado do servidor, "Modo assíncrono" é o único modo, porque o ambiente de execução é um único thread, se todas as solicitações HTTP puderem ser executadas de maneira síncrona, o desempenho do servidor cairá acentuadamente e em breve perderá sua resposta.
1. Função de retorno de chamada
Este é o método mais básico de programação assíncrona.
Suponha que haja duas funções F1 e F2, a última aguardando o resultado da execução do primeiro.
A cópia do código é a seguinte:
f1 ();
f2 ();
Se a F1 for uma tarefa demorada, você pode considerar reescrever a F1 e escrever F2 como a função de retorno de chamada da F1.
A cópia do código é a seguinte:
função f1 (retorno de chamada) {
setTimeout (function () {
// Código de tarefas da F1
ligar de volta();
}, 1000);
}
O código de execução se torna assim:
F1 (F2);
A vantagem das funções de retorno de chamada é que elas são simples, fáceis de entender e implantar, e a desvantagem é que eles não são propícios à leitura e manutenção do código. Muito caótico, e cada tarefa pode especificar apenas uma função de retorno de chamada.
2. Monitoramento de eventos
Outra idéia é adotar um modelo orientado a eventos. A execução de uma tarefa não depende da ordem do código, mas se ocorre um evento.
Vamos tomar F1 e F2 como exemplos. Primeiro, vincule um evento para F1 (o método de redação do jQuery usado aqui).
A cópia do código é a seguinte:
f1.on ('feito', f2);
A linha de código acima significa que, quando o evento feito ocorre em F1, F2 será executado. Então, reescreva F1:
A cópia do código é a seguinte:
função f1 () {
setTimeout (function () {
// Código de tarefas da F1
F1.Trigger ('done');
}, 1000);
}
F1.Trigger ('Done') significa que, após a conclusão da execução, o evento feito é acionado imediatamente, começando a executar F2.
A vantagem desse método é que é relativamente fácil de entender. A desvantagem é que todo o programa se tornará orientado a eventos e o processo de operação se tornará muito claro.
3. Publique/assine
O "evento" na seção anterior pode ser totalmente compreendido como um "sinal".
Assumimos que existe um "Signal Center". Isso é chamado de "Publicar-Subscribe Pattern", também conhecido como "Padrão de Observador".
Existem muitas implementações deste modelo.
Primeiro, o F2 assina o sinal "feito" para o jQuery "Signal Center".
A cópia do código é a seguinte:
jQuery.subScribe ("done", f2);
Então, F1 é reescrito da seguinte maneira:
A cópia do código é a seguinte:
função f1 () {
setTimeout (function () {
// Código de tarefas da F1
jQuery.publish ("feito");
}, 1000);
}
JQuery.publish ("feito") significa que, após a conclusão da execução da F1, um sinal "feito" é emitido para o jQuery "Signal Center", desencadeando assim a execução de F2.
Além disso, após a execução do F2, a inscrição na inscrição também pode ser cancelada.
A cópia do código é a seguinte:
jQuery.UnsubScribe ("Done", F2);
A natureza dessa abordagem é semelhante à "escuta do evento", mas é significativamente melhor que a última. Porque podemos monitorar a operação do programa analisando o "centro de mensagens" para entender quantos sinais existem e quantos assinantes são para cada sinal.
4. Promessas objeto
O objeto de promessas é uma especificação proposta pelo Grupo de Trabalho Commonjs, com o objetivo de fornecer uma interface unificada para programação assíncrona.
Simplificando, sua idéia é que cada tarefa assíncrona retorne um objeto de promessa, que possui um método então que permite que a função de retorno de chamada seja especificada. Por exemplo, a função de retorno de chamada F2 de F1 pode ser escrita como:
A cópia do código é a seguinte:
f1 (). Então (f2);
F1 precisa ser reescrito da seguinte forma (a implementação do jQuery é usada aqui):
A cópia do código é a seguinte:
função f1 () {
var dfd = $ .Deferred ();
setTimeout (function () {
// Código de tarefas da F1
dfd.resolve ();
}, 500);
retornar dfd.promise;
}
A vantagem de escrever dessa maneira é que a função de retorno de chamada se tornou um método de escrita em cadeia, e o fluxo do programa pode ser visto com muita clareza, e há um conjunto completo de métodos de suporte que podem realizar muitas funções poderosas.
Por exemplo, especifique várias funções de retorno de chamada:
f1 (). Então (f2) .Enthen (f3);
Por exemplo, especifique a função de retorno de chamada quando ocorrer um erro:
f1 (). Então (f2) .Fail (f3);
Além disso, tem uma vantagem que nenhum dos três métodos anteriores possui: se uma tarefa foi concluída, adicione uma função de retorno de chamada e a função de retorno de chamada será executada imediatamente. Portanto, você não precisa se preocupar em perder um evento ou sinal. A desvantagem desse método é que é relativamente difícil de escrever e entender.