Prefácio
O maior destaque do NodeJS é o modelo de E/S sem bloqueio, orientado a eventos, que faz com que o NodeJS tenha fortes recursos de processamento de simultaneidade e é muito adequado para escrever aplicativos de rede. A maioria das operações de E/S nos NodeJs é quase assíncrona, ou seja, os resultados de nossas operações de E/S basicamente precisam ser processados na função de retorno de chamada, como a seguinte função que lê o conteúdo do arquivo:
A cópia do código é a seguinte:
fs.readfile ('/etc/passwd', function (err, dados) {
se (err) lançar err;
console.log (dados);
});
Então, o que devemos fazer se lermos dois arquivos e mesclar o conteúdo desses dois arquivos juntos? A maioria das pessoas que não estão em contato com JS pode fazer isso:
A cópia do código é a seguinte:
fs.readfile ('/etc/passwd', function (err, dados) {
se (err) lançar err;
fs.readfile ('/etc/passwd2', function (err, data2) {
se (err) lançar err;
// Processar dados de dados e dados2 aqui
});
});
Se você lidar com vários cenários semelhantes, não seria que as funções de retorno de chamada sejam camadas aninhadas por camada? É isso que as pessoas costumam chamar de pirâmide ou inferno de retorno de chamada (http://callbackhell.com/), e também é o problema mais problemático para o JS Novice.
Esse tipo de código aninhado trouxe muitos problemas ao desenvolvimento, refletiu principalmente em:
1. A possibilidade de código se torna pior
2. Dificuldades de depuração
3. É difícil verificar depois que ocorre uma exceção
Este artigo apresenta principalmente como lidar com os problemas de retorno de chamada assíncronos acima.
Solução primária: processe recursivamente retornos de chamada assíncronos
Podemos usar a recursão como ferramenta de controle de execução para o código. Encapsular as operações que precisam ser executadas em uma função e controlar o processo de execução do código, chamando recursivamente a função de retorno de chamada. Sem mais delongas, vamos falar sobre bobagem, vamos dar uma olhada no código anterior:
A cópia do código é a seguinte:
var fs = requer ('fs');
// Lista de arquivos a serem processados
var arquivos var = ['file1', 'file2', 'file3'];
função parsefile () {
if (files.length == 0) {
retornar;
}
var arquivo = files.shift ();
fs.readfile (arquivo, função (err, dados) {
// Processar dados do arquivo aqui
parsefile (); // Após o processamento, processe o próximo arquivo por meio de chamada recursiva
});
}
// Iniciar o processamento
parsefile ();
O código acima processou os arquivos na matriz, por sua vez, como exemplo, introduzindo o processo de execução de controlar o código por meios recursivos.
É bom aplicá -lo a alguns cenários simples, como: podemos usar esse método salvando os dados em uma matriz no banco de dados por sua vez.
Recursivamente, alguns problemas simples de retorno de chamada assíncronos podem ser resolvidos. No entanto, ainda parece impotente lidar com retornos de chamada assíncronos complexos (como sincronizar os resultados de várias operações assíncronas).
Ponto lindo: use bibliotecas de terceiros, como async, q, prometem lidar com retornos de chamada assíncronos
Para lidar melhor com retornos de chamada aninhados, você pode considerar o uso de algumas bibliotecas de terceiros que lidam especificamente com assíncrono. Obviamente, se você tiver a habilidade, pode escrever uma ferramenta auxiliar para processamento assíncrono sozinho.
As bibliotecas mais usadas para lidar com o processamento assíncrono são: assíncrono, q e promessa. A julgar pelo site do NPMJS.org, o Async é o mais popular. Eu já usei o Async antes, e é realmente bastante conveniente, e vários fluxos de controle de processamento assíncronos são bem implementados.
Usaremos o Async para processar o código que lê inicialmente dois arquivos ao mesmo tempo, como mostrado abaixo:
A cópia do código é a seguinte:
var assync = requer ('assíncrono')
, fs = requer ('fs');
async.parallel ([
função (retorno de chamada) {
fs.readfile ('/etc/passwd', function (err, dados) {
se (err) retorno de chamada (err);
retorno de chamada (nulo, dados);
});
},
função (retorno de chamada) {
fs.readfile ('/etc/passwd2', function (err, data2) {
se (err) retorno de chamada (err);
retorno de chamada (null, data2);
});
}
],
função (err, resultados) {
// Processar dados de dados e dados2 aqui, e o conteúdo de cada arquivo é obtido dos resultados
});
Através do módulo assíncrono, o processo de execução assíncrono pode ser bem controlado, o que também pode resolver o problema dos retornos de chamada em camadas. O código é mais claro do que antes, mas ainda não pode ser separado da função de retorno de chamada.
Pense nisso, seria ótimo se você pudesse lidar com o assíncrono sem usar funções de retorno de chamada. Em seguida, vamos falar sobre o uso dos novos recursos do ES6 para atingir esse objetivo.
Ponto elegante: abraça ES6, substitua as funções de retorno de chamada e resolva o problema do inferno de retorno de chamada
A propósito, o ECMAScript Harmony (ES6) introduziu muitos novos recursos no JS. Os alunos que não sabem muito sobre o ES6 podem dar uma olhada no Baidu por conta própria.
Para usar os novos recursos do ES6 no NodeJS, você precisa usar v0.11.x ou acima.
Este artigo apresenta o uso do recurso gerador em vez de funções de retorno de chamada. Não sabe sobre o gerador? Você pode conferir aqui.
Aqui usamos dois módulos CO e Thunkify, e usamos o comando NPM Install para instalá -lo.
Pegue o problema mencionado no início deste artigo como exemplo. O código de exemplo usando o recurso gerador é o seguinte:
A cópia do código é a seguinte:
var fs = requer ('fs')
, co = requer ('co')
, Thunkify = requer ('Thunkify');
var readfile = thunkify (fs.readfile);
CO (função *() {
var test1 = readfile de readfile ('test1.txt');
var test2 = readfile de readfile ('test2.txt');
var test = test1.toString () + test2.toString ();
console.log (teste);
}) ();
Também é muito simples lidar com exceções no código, faça -o da seguinte:
A cópia do código é a seguinte:
tentar {
var test1 = readfile de readfile ('test1.txt');
} catch (e) {
// lida com exceções aqui
}
Esse tipo de código é muito mais elegante? Não é ótimo lidar com o código síncrono de escrita de forma assíncrona?
A estrutura mais popular para o desenvolvimento da Web no campo NodeJS é expressa. Vale ressaltar que o membro principal do Express TJ, o grande mestre do Express, liderou uma nova estrutura da web - Koa, que afirma ser a próxima geração de estrutura de desenvolvimento da Web. O KOA realmente usa o recurso do gerador ES6 para nos ajudar a evitar cair em camadas de retornos de chamada ao desenvolver o sistema da Web.
Resumir
Cite uma frase da promoção do projeto FIBJS: menos retorno de chamada, mais meninas - menos retornos de chamada, mais garotas