Acabei de começar a usar o nó, e uma coisa que notei rapidamente é a rapidez com que os retornos de chamada podem criar um nível bobo de recuo:
doStuff(arg1, arg2, function(err, result) {
doMoreStuff(arg3, arg4, function(err, result) {
doEvenMoreStuff(arg5, arg6, function(err, result) {
omgHowDidIGetHere();
});
});
});
O guia de estilo oficial diz para colocar cada retorno de chamada em uma função separada, mas isso parece excessivamente restritivo ao uso de fechamentos e tornar um único objeto declarado no nível superior disponível várias camadas abaixo, pois o objeto deve ser passado por todas as retornos de chamada intermediários.
É bom usar o escopo da função para ajudar aqui? Coloque todas as funções de retorno de chamada que precisam acessar um objeto global-ish dentro de uma função que declare esse objeto, para que ele seja encerrado?
function topLevelFunction(globalishObject, callback) {
function doMoreStuffImpl(err, result) {
doMoreStuff(arg5, arg6, function(err, result) {
callback(null, globalishObject);
});
}
doStuff(arg1, arg2, doMoreStuffImpl);
}
e assim por diante por várias outras camadas ...
Ou existem estruturas etc para ajudar a reduzir os níveis de recuo sem declarar uma função nomeada para cada retorno de chamada? Como você lida com a pirâmide de retorno de chamada?
fonte
Respostas:
Existem várias implementações de "promessas":
Por exemplo, você pode reescrever esses retornos de chamada aninhados
gostar
Em vez de retorno de chamada,
a(b(c()))
você liga o ".then"a().then(b()).then(c())
.Uma introdução aqui: http://howtonode.org/promises
fonte
Como alternativa às promessas, você deve dar uma olhada na
yield
palavra - chave em combinação com as funções do gerador que serão introduzidas no EcmaScript 6. Ambas estão disponíveis hoje nas compilações do Node.js. 0.11.x, mas exigem que você especifique adicionalmente o--harmony
sinalizador ao executar o Node .js:Usando essas construções e uma biblioteca como do TJ Holowaychuk co permitem escrever código assíncrono em um estilo que olha como código síncrono, embora ele ainda funciona de forma assíncrona. Basicamente, essas coisas juntas implementam suporte co-rotineiro para Node.js.
Basicamente, o que você precisa fazer é escrever uma função geradora para o código que executa coisas assíncronas, chamar as coisas assíncronas, mas prefixar com a
yield
palavra - chave. Portanto, no final, seu código se parece com:Para executar esta função geradora, você precisa de uma biblioteca como a co mencionada anteriormente. A chamada então se parece com:
Ou, para colocar em linha:
Observe que nas funções do gerador você pode chamar outras funções do gerador, tudo o que você precisa fazer é prefixá-las
yield
novamente.Para uma introdução a este tópico, pesquise no Google termos como
yield generators es6 async nodejs
e você deve encontrar toneladas de informações. Demora um tempo para se acostumar, mas depois que você o obtém, não deseja mais voltar.Observe que isso não apenas fornece uma sintaxe melhor para chamar funções, mas também permite que você use as coisas lógicas usuais (síncronas) do fluxo de controle, como
for
loops outry
/catch
. Chega de brincar com muitas retornos de chamada e todas essas coisas.Boa sorte e divirta-se :-)!
fonte
Agora você tem o pacote asyncawait , com uma sintaxe muito próxima do que deve ser o futuro suporte nativo do
await
&async
in Node.Basicamente, ele permite que você escreva códigos assíncronos com aparência síncrona , reduzindo drasticamente os níveis de LOC e recuo, com a compensação de uma pequena perda de desempenho (os números dos proprietários dos pacotes têm uma velocidade de 79% em comparação com os retornos brutos), esperançosamente reduzidos quando o suporte nativo estiver disponível.
Ainda é uma boa opção para sair da IMO do inferno de retorno de chamada / pirâmide do pesadelo, quando o desempenho não é a principal preocupação e o estilo de escrita síncrona melhor se adapta às necessidades do seu projeto.
Exemplo básico do pacote doc:
fonte