Durante o processo de escrever node.js, as operações contínuas de IO podem levar a "pesadelo da pirâmide". O ninho múltiplo das funções de retorno de chamada dificulta o código. A promessa do CommonJS é usada para encapsular funções assíncronas e usar uma API de cadeia unificada para se livrar do pesadelo de vários retornos de chamada.
O modelo de IO não bloqueador fornecido pelo Node.js nos permite usar funções de retorno de chamada para lidar com operações de IO, mas quando as operações contínuas de IO forem necessárias, suas funções de retorno de chamada serão aninhadas várias vezes, o código não é bonito e não é fácil de manter e pode haver muitos códigos repetidos para manipular de erros, qual é o chamado "Sofamid dos" atribuídos a partir de ", e pode haver muitos códigos repetidos.
A cópia do código é a seguinte:
Etapa1 (função (value1) {
Etapa2 (Value1, Função (Value2) {
Etapa3 (Value2, Função (Value3) {
Etapa4 (valor3, função (valor4) {
// Faça algo com valor4
});
});
});
});
Este é realmente o problema do fluxo de controle no Node.js. Existem muitas soluções para esse problema, como usar async, eventproxy, etc. No entanto, o tópico deste artigo é usar a promessa na especificação Commonjs para resolver esse problema.
O que é promessa?
Existem muitos tipos de especificações de promessa para CommonJs. Geralmente discutimos a especificação Promise/A+, que define o comportamento básico da promessa.
Uma promessa é um objeto que geralmente representa uma operação assíncrona que pode ser concluída no futuro. Esta operação pode ter sucesso ou falhar; portanto, um objeto de promessa geralmente possui 3 estados: pendente, cumprido e rejeitado. Representa a falha inacabada e bem -sucedida de conclusão e operação, respectivamente. Uma vez que o estado da promessa o objeto muda de pendente para cumprido ou rejeitado, seu estado não pode ser alterado novamente.
Um objeto de promessa geralmente possui um método então, que nos permite operar o valor retornado após possível sucesso no futuro ou o motivo da falha. Este método se parece com o seguinte:
Promise.HETHEN (Onfulfilled, OnRejeded)
É óbvio que o método então aceita dois parâmetros, que geralmente são duas funções, um é usado para processar o resultado após o sucesso da operação e o outro é usado para processar a causa da falha da operação. Os primeiros parâmetros dessas duas funções são o resultado após o sucesso e a causa da falha. Se o método então não for uma função, esse parâmetro será ignorado.
O valor de retorno do método então é um objeto de promessa, que nos permite encadear a chamada para alcançar o efeito de controlar o processo. Existem muitos detalhes aqui, como transferência de valor ou manuseio de erros. A especificação da promessa é definida assim:
O valor de retorno da função Onfulfilled ou OnRejeded não é um objeto de promessa; o valor será usado como o primeiro parâmetro de Onfulfilless no próximo método. Se o valor de retorno for um objeto de promessa, como o valor de retorno do método pode ser o objeto de promessa
Se uma exceção for lançada na função de retenção ou on -rejeitada, o status do objeto de promessa retornado do método será convertido para rejeitada. Se o objeto Promise Chank, o objeto de erro será usado como o primeiro parâmetro da função on -rejeitada.
Se o estado da promessa for cumprido e a função de realização não for fornecida no método então, o estado do objeto de promessa retornado pelo método então é cumprido e o resultado bem -sucedido é o resultado da promessa anterior, o mesmo é verdadeiro para rejeitado.
Para acrescentar, tanto o Onfulfilled quanto o OnRejected são executados de forma assíncrona.
Implementação da especificação: Q
O exposto acima é sobre a especificação da promessa, e o que precisamos é de sua implementação. Q é uma biblioteca que possui melhores especificações de implementação para Promise/A+.
Primeiro de tudo, precisamos criar um objeto de promessa. As especificações para a criação do objeto Promise estão em promessa/b. Não vou explicar em detalhes aqui, basta adicionar o código.
A cópia do código é a seguinte:
função (sinalizador) {
var difer = q.defer ();
fs.readfile ("a.txt", function (err, dados) {
if (err) adie.reject (err);
else difer.resolve (dados);
});
return difer.promise;
}
A maioria das implementações de promessa é semelhante na criação de promessas. Ao criar um objeto de adiamento com atributo de promessa, se o valor for obtido com sucesso, o adefer.Resolve (valor) será chamado, se falhar, adiar.reject (Motivo) é chamado e, finalmente, retorne o atributo de promessa de adiar. Esse processo pode ser entendido como chamando adiamento.Resolve transforma o estado da promessa em cumprimento e chamando o adiFer.Reject transforma o estado da promessa em rejeição.
Ao enfrentar uma série de métodos assíncronos contínuos, como você pode escrever um belo código usando a promessa? Dê uma olhada no exemplo a seguir.
A cópia do código é a seguinte:
Promote0.then (função (resultado) {
// doSomething
resultado de retorno;
}). Então (função (resultado) {
// doSomething
devolver promessa1;
}). Então (função (resultado) {
// doSomething
}). Catch (function (ex) {
console.log (ex);
}). Finalmente (function () {
console.log ("final");
});
No código acima, o método então aceita apenas o reivindicação e o método de captura é na verdade (nulo, contratado). Dessa forma, enquanto uma série de métodos assíncronos sempre retorna valores com sucesso, o código será descendente em um estilo de cascata. Se algum dos métodos assíncronos falhar ou ocorrer uma exceção, de acordo com a especificação do CommonJS Promise, a função na captura será executada. Q também fornece o método finalmente, que é fácil de entender literalmente, ou seja, se resolve ou rejeita, a função finalmente será executada.
Parece bom, o código é mais mantido e bonito, e se você quiser simultaneidade?
A cópia do código é a seguinte:
Q.All ([Promise0, Promise1, Promise2].
console.log (argumentos);
}). Então (function () {
console.log ("feito");
}). Catch (function (err) {
console.log (err);
});
Q também fornece uma API para a simultaneidade, chamando todos os métodos e a aprovação de uma matriz de promessa pode continuar a usar o estilo da corrente. Também existem coisas boas como q.nfbind, etc. que podem converter a API nativa do Node.js em promessa de unificar o formato de código. Mais APIs não serão descritas em detalhes aqui.
para concluir
Este artigo apresenta principalmente o uso da promessa para resolver o problema do fluxo de controle do node.js, mas a promessa também pode ser aplicada ao front-end. O EMCascript6 forneceu suporte à API nativa. Deve -se ressaltar que a promessa não é a única solução, o Async também é uma boa escolha e fornece uma API de controle de simultaneidade mais amigável, mas acho que a promessa tem mais vantagens ao encapsular funções com métodos assíncronos.
Ok, isso é tudo para este artigo, espero que seja útil para todos.