Inferno de retorno de chamada
Para programadores de JavaScript, o manuseio de retornos de chamada é caseiro, mas lidar com retornos de chamada com níveis muito profundos não é tão bonito. O snippet de código de amostra a seguir usa retornos de chamada de três camadas e, em seguida, reabastece o cérebro para obter mais camadas de cenas. É simplesmente azedo. Este é o lendário inferno de retorno de chamada.
getDirectories (function (dirs) {getFiles (dirs [0], function (arquivos) {getContent (arquivos [0], function (arquivo, content) {console.log ('nome do arquivo:', arquivo); console.log (content);});});}); função getDirectories (retorno de chamada) {setTimeout (function () {retorno de chamada (['/home/ben']);}, 1000);} função getFiles (dir, retorno de chamada) {setTimeout (function () {callback ([dir + '/test1.txt', dir + '/test2.txt']; setTimeout (function () {retorno de chamada (arquivo, 'content');}, 1000)}Solução
Existem muitas soluções assíncronas no ecossistema que podem lidar com o problema do inferno de retorno de chamada, como Bluebird, Q, etc. Este artigo se concentra no suporte para programação assíncrona na especificação Ecmascript 6/7.
ES6 Promessa
A Promise é uma solução para programação assíncrona e uma ferramenta poderosa para resolver o problema do inferno de retorno de chamada.
A promessa foi aceita com base no ecossistema JavaScript em 2007, quando a estrutura do dojo adicionou a funcionalidade do dojo.deferred. Com a popularidade do Dojo.Deferred, em 2009, Kris Zyp propôs as promessas da Commonjs/uma especificação. Posteriormente, um grande número de implementações de promessa apareceu no ecossistema, incluindo Q.Js, FuturesJs, etc. É claro que a popularidade da promessa se deve em grande parte à existência de jQuery, mas o jQuery não cumpre as promessas Commonjs/uma especificação. Então, como você pode ver, a especificação ES 6 inclui a promessa.
A promessa é descrita no MDN da seguinte forma:
O objeto Promise é um proxy para o valor de retorno, que pode não ser conhecido quando o objeto Promise é criado. Ele permite especificar um método de manuseio para sucesso ou falha de uma operação assíncrona. Isso permite que o método assíncrono retorne um valor como um método síncrono: o método assíncrono retorna um valor de retorno original
O código a seguir é um exemplo na seção "Inferno de retorno de chamada" implementada por meio da promessa. O código não parece muito conciso, mas melhorou significativamente em comparação com os retornos hierárquicos tradicionais, e o código é mais sustentável e legível.
getDirectories (). Então (function (dirs) {return getFiles (dirs [0]);}). Então (function (arquivos) {return getContent (files [0]);}). então (function (val) {console.log ('filename:', val.File); console.log (val.ontent); function getDirectories () {return New Promise (function (resolve, rejeite) {setTimeout (function () {resolve (['/home/ben']);}, 1000);});} function getFiles (dir) {return (function (resolve, rejejeção) {settimeout (function () {(resolver) (resolver (resolver (resolver) {settimeOut () () {retr) {Return (function (resolve, reject) {settimeout (), () {resolv). '/test2.txt']);GERADOR ES6
A implementação da promessa não é simples o suficiente, ainda precisamos de uma escolha melhor e o CO é uma das opções. O CO é um controlador de fluxo assíncrono baseado no gerador. Antes de entender o CO, você precisa entender o gerador primeiro. Os alunos que estão familiarizados com o C# devem entender que a versão C# 2.0 apresenta a palavra -chave de rendimento para iterar o gerador. O gerador ES 6 é semelhante ao C#e também usa o açúcar de sintaxe de rendimento e implementa uma máquina de estado internamente. Para uso específico, consulte a seção MDN Document Function* e consulte o blog da equipe de liga de liga para obter uma compreensão aprofundada do gerador. Use o CO para combinar inteligentemente o gerador ES6 e o ES6 prometem fazer chamadas assíncronas mais harmoniosas.
CO (função* () {var dirO CO é muito inteligente e seu código principal pode simplificar o exemplo a seguir. A idéia geral é usar o gerador de travessia recursivo até que o estado seja concluído, é claro que a CO faz mais.
rungenerator (); function* run () {var dir Arquivos var = rendimento getfiles (dirs [0]); var contentVal = rendimento getContent (arquivos [0]); console.log ('nome do arquivo:', contentVal.File); console.log (contentVal.Content);} função rungenerator () {var gen = run (); função go (resultado) {if (resultado.done) return; resultado.value.then (function (r) {go (gen.next (r));}); } go (gen.Next ());}ES7 ASYNC/AWAIT
O gerador ES6 é muito bom, mas é uma pena que eu precise do suporte de uma biblioteca de terceiros. A boa notícia é que o ES 7 apresentará a palavra -chave Async/Aguarda para resolver perfeitamente o problema das chamadas assíncronas. Bem, o .NET está um passo à frente e o .NET Framework 4.5 já é o primeiro a apoiá -lo.
O código futuro será escrito assim:
run (); função assíncrona run () {var dir Arquivos var = aguarda getFiles (dirs [0]); var contentVal = aguarda getContent (arquivos [0]); console.log ('nome do arquivo:', contentVal.File); console.log (ContentVal.Content);}para concluir
Desde o clássico método de programação assíncrona de retorno de chamada, até a melhoria da programação assíncrona pela especificação da promessa ES6, ao elegante processamento de co-combinados com o gerador ES e, finalmente, o final perfeito de ES7 assíncrono/aguardar, podemos entender por que o ECMAScript tem esses recursos e os problemas que ele solve e veja mais claramente o desenvolvimento do JAVASSCRANTS.