Este artigo populariza principalmente o uso de promessas.
Por um longo tempo, o JavaScript sempre lidou com o assíncrono na forma de retorno de chamada, e o mecanismo de retorno de chamada no campo do desenvolvimento do front-end está quase profundamente enraizado no coração do povo. Ao projetar APIs, seja um fabricante de navegador, desenvolvedor SDK ou autor de várias bibliotecas, eles basicamente seguem a rotina de retorno de chamada.
Nos últimos anos, com a maturidade gradual do modelo de desenvolvimento de JavaScript, nasceu a especificação CommonJS, incluindo a proposta da especificação da promessa. A promessa mudou completamente a escrita da programação assíncrona do JS, facilitando o entendimento da programação assíncrona.
No modelo de retorno de chamada, assumimos que uma fila assíncrona precisa ser executada, e o código pode ser assim:
loadImg ('A.Jpg', function () {loadImg ('B.JPG', function () {loadImg ('c.jpg', function () {console.log ('tudo feito!');});});});É isso que frequentemente pirâmide de retorno de chamada. Quando houver muitas tarefas assíncronas, manter um grande número de retornos de chamada será um desastre. Atualmente, o Node.js é muito popular. Parece que muitas equipes querem usá -lo para fazer algo para se dar bem com a "moda". Depois de conversar com um colega de operação e manutenção, eles também planejavam usar o Node.js para fazer alguma coisa, mas quando pensam nas camadas de retornos de chamada de JS, eles são desencorajados.
Ok, o absurdo acabou, vamos ao tópico.
A promessa pode estar familiarizada com todos, porque a especificação da promessa está fora há muito tempo, e a promessa foi incluída no ES6, e as versões mais altas dos navegadores do Chrome e do Firefox implementaram a promessa nativamente, mas há menos APIs do que a popular biblioteca de classes de promessa hoje em dia.
A chamada promessa pode ser literalmente entendida como "promessa", o que significa que A chama B, B retorna uma "promessa" a A, e depois a pode escrever isso ao escrever o plano: quando B retornar o resultado para mim, um plano executa S1. Pelo contrário, se B não fornecer o resultado desejado por algum motivo, um plano de emergência executa S2, para que todos os riscos potenciais estejam dentro da faixa controlável de A.
A frase acima é traduzida em código semelhante a:
var resb = b (); var runA = function () {resb.then (execs1, execs2);}; runa ();Apenas olhando para a linha de código acima, parece que não há nada de especial. Mas a realidade pode ser muito mais complicada do que isso. Para realizar uma coisa, pode confiar na resposta de mais de uma pessoa B. Pode exigir pedir a várias pessoas ao mesmo tempo e, em seguida, implementar o próximo plano depois de receber todas as respostas. A tradução final para o código pode ficar assim:
var resb = b (); var rescn = c (); ... var runA = function () {reqb .Then (resgin, execs2) .then (resd, execs3) .then (rese, execs4) .....Aqui, diferentes mecanismos de processamento são usados quando cada uma pergunta responde que não estão alinhadas com as expectativas. De fato, a especificação da promessa não requer isso e você pode até não fazer nada (ou seja, não passar no segundo parâmetro de então) ou lidar com ele uniformemente.
OK, vamos conhecer as especificações Promessa/A+:
then (pode -se dizer que é o núcleo da promessa) e, em seguida, deve devolver uma promessa. Então, da mesma promessa pode ser chamada várias vezes, e a ordem de execução dos retornos de chamada é consistente com a ordem quando são definidosComo você pode ver, não há muito conteúdo na especificação da promessa, para que você possa tentar implementar a seguinte promessa.
A seguir, é apresentada uma simples implementação de uma promessa de que referenciei muitas bibliotecas de promessas. Por favor, mude para o Promisea no código.
Uma breve análise das idéias:
A promessa do construtor aceita um resolver de função, que pode ser entendido como passando uma tarefa assíncrona. O resolvedor aceita dois parâmetros, um é um retorno de chamada quando bem -sucedido e o outro é um retorno de chamada quando falha. Esses dois parâmetros são iguais aos parâmetros passados pela época.
O segundo é a implementação de então. Como a promessa exige que, em seguida, devolva uma promessa, será gerada uma nova promessa quando chamado, que será pendurado _next da promessa atual. Várias chamadas da mesma promessa retornarão apenas o _next gerado anteriormente.
Como os dois parâmetros aceitos pelo método então são opcionais e não há restrição no tipo, ele pode ser uma função, um valor específico ou outra promessa. Aqui está a implementação específica de então:
Prometo.prototype.Then = function (resolver, rejeitar) {var next = this._next || (this._next = Promise ()); var status = this.status; var x; if ('pendente' === status) {isfn (resolve) && this._resolves.push (resolve); isfn (rejeitar) && this._rejects.push (rejeitar); retornar a seguir; } if ('resolvido' === status) {if (! isfn (resolve)) {next.resolve (resolve); } else {try {x = resolve (this.value); resolvex (a seguir, x); } catch (e) {this.reject (e); }} retornar a seguir; } if ('rejeitou' === status) {if (! isfn (rejeit)) {next.Reject (rejeit); } else {try {x = rejeit (this.Reason); resolvex (a seguir, x); } catch (e) {this.reject (e); }} retornar a seguir; }};Aqui, simplificou a implementação de outras bibliotecas de classes de promessas, e a implementação é muito mais complexa que isso e também possui mais funções. Por exemplo, existe um terceiro parâmetro - notificar, que indica o progresso atual da promessa, o que é muito útil ao fazer o upload de arquivos de design, etc. O processamento de vários parâmetros de então é a parte mais complicada. Os alunos interessados podem se referir à implementação de outros tipos de bibliotecas de promessas.
Com base em, então, pelo menos dois métodos devem ser necessários, a saber, para concluir a conversão do estado da promessa de pendente para resolvido ou rejeitado, e para executar os métodos correspondentes de retorno de chamada, ou seja, resolve() e reject() métodos.
Neste ponto, uma promessa simples foi projetada. A seguir, são apresentadas implementações simples das duas funções prometidas a seguir:
função sono (ms) {return function (v) {var p = promeso (); setTimeout (function () {p.Resolve (v);}, ms); retornar p; };}; função getImg (url) {var p = promeso (); var iMg = new Image (); img.onload = function () {p.Resolve (this); }; img.onerror = function (err) {p.reject (err); }; img.url = url; retornar p;}; Como o construtor da promessa aceita uma tarefa assíncrona como um parâmetro, getImg também pode ser chamado assim:
function getImg (url) {return promey (function (resolve, rejeite) {var iMg = new image (); img.onload = function () {resolve (this);}; img.onerror = function (err) {rejeit (err);}; img.url = url;});};Em seguida (o momento de testemunhar o milagre), suponha que haja um requisito de BT para implementar isso: obtenha uma configuração JSON de forma assíncrona, analise os dados do JSON e obtenha as fotos dentro e, em seguida, carregue as imagens em sequência e dê um efeito de carregamento quando nenhuma imagem é carregada.
function addimg (img) {$ ('#list'). find ('> li: Última filho'). html (''). Append (img);}; função precend () {) ('<li>') .html ('carregamento ...') .ppend ($ ('#list'));}; getData ('map.json') .then (function (dados) {$ ('h4'). html (data.name); retorna data.list.reduce (function (promete, item) {return promey .then (add) .then (sleep (1000) .then). Promete.resolve ());O sono aqui é adicionado apenas para ver o efeito, você pode clicar para ver a demonstração! Obviamente, o exemplo do Node.js pode ser visto aqui.
Aqui, o método estático de Promise.resolve(v) simplesmente retorna uma promessa com V como resultado positivo. V não pode ser passado, ou pode ser uma função ou um objeto ou função que contém then método (ou seja, então capaz).
Métodos estáticos semelhantes incluem Promise.cast(promise) , que gera uma promessa com promessa como resultado positivo;
Promise.reject(reason) gera uma promessa com razão como resultado negativo.
Nossos cenários de uso reais podem ser muito complexos e geralmente exigem que várias tarefas assíncronas sejam executadas intercaladas, paralelas ou em série. Nesse momento, você pode fazer várias extensões a prometer, como implementar Promise.all() , aceitando as promessas na fila e aguardando a conclusão antes de continuarem e, por exemplo, Promise.any() .
Você pode se referir a este artigo nas promessas do HTML5Rocks JavaScript. Atualmente, navegadores avançados como Chrome e Firefox têm objetos de promessa integrados, fornecendo mais interfaces de operação, como Promise.all() , que suporta a passagem de uma matriz de promessas e, em seguida, executa quando todas as promessas são concluídas. Há também uma captura de exceção mais amigável e poderosa, que deve ser suficiente para lidar com a programação assíncrona diária.
As bibliotecas JS mais populares hoje implementaram promessas de graus variados, como Dojo, JQuery, Zepto, quando.js, Q, etc., mas a maioria dos objetos expostos Deferred . Tomando jQuery (zepto semelhante) como um exemplo, implemente o getImg() acima:
function getImg (url) {var def = $ .Deferred (); var iMg = new Image (); img.onload = function () {def.resolve (this); }; img.onerror = function (err) {def.reject (err); }; img.src = url; return def.promise ();}; Obviamente, no jQuery, muitas operações retornam ou prometem, como animate e ajax :
// ajax $ .ajax (opacidade ': 0}, 1000) .promise () .then (function () {console.log (' done ');}); // ajax $ .ajax (options) .then (sucess, falha); $. ajax (opções) .done (succcess) .fil); $ .ajax (options2)) .then (function () {console.log ('tudo feito.');}, function () {console.error ('lá algo errado.');}); O jQuery também implementa done() e fail() , que na verdade são atalhos do método então.
Para lidar com as filas de promessas, o jQuery implementa $.when() , e seu uso é semelhante ao Promise.all() .
Para outras bibliotecas de classes, vale a pena mencionar aqui que, quando o.js tem pouco código, ele implementa totalmente, suporta o navegador e o Node.js e fornece APIs mais ricas, o que é uma boa escolha. Devido a limitações de espaço, não o expandiremos mais.
Vemos que, por mais complexa que seja a implementação da promessa, seu uso é muito simples e o código organizacional é muito claro. A partir de agora, não há necessidade de ser torturado por retorno de chamada.
Finalmente, a promessa é tão elegante! Mas a promessa resolve apenas o problema do ninho profundo dos retornos de chamada. É o gerador que realmente simplifica a programação assíncrona JavaScript. No lado Node.js, é recomendável considerar o gerador.
Próximo artigo, gerador de estudo.
GitHub Texto original: https://github.com/chemdemo/chemdemo.github.io/issues/6