Hellback Hell
Pour les programmeurs JavaScript, la gestion des rappels est simple, mais gérer les rappels avec des niveaux trop profonds n'est pas si beau. L'exemple d'extrait de code suivant utilise des rappels à trois couches, puis reconstitue le cerveau pour plus de couches de scènes. C'est simplement aigre. C'est l'enfer légendaire de rappel.
getDirectories (function (dirs) {getFiles (dirs [0], function (files) {getContent (files [0], fonction (fichier, contenu) {console.log ('filename:', file); console.log (contenu);});});}); function getDirectries (callback) {setTimeout (function () {callback (['/ home / ben']);}, 1000);} fonction getFiles (dir, callback) {setTimeout (function () {callback ([dir + '/test1.txt', dir + '/test2 setTimeout (function () {callback (fichier, 'contenu');}, 1000)}Solution
Il existe de nombreuses solutions asynchrones dans l'écosystème qui peuvent gérer le problème de l'enfer de rappel, comme Bluebird, Q, etc. Cet article se concentre sur le support de la programmation asynchrone dans la spécification ECMAScript 6/7.
Promesse ES6
Promise est une solution pour la programmation asynchrone et un outil puissant pour résoudre le problème de l'enfer de rappel.
La promesse a été acceptée grand public dans l'écosystème JavaScript en 2007 lorsque le framework Dojo a ajouté la fonctionnalité de Dojo.Deferred. Avec la popularité de Dojo.Deferred, en 2009, Kris Zyp a proposé les spécifications de promesses / une spécification CommonJS. Par la suite, un grand nombre d'implémentations de promesses sont apparues dans l'écosystème, notamment Q.JS, FuturesJS, etc. Bien sûr, la popularité de la promesse est largement due à l'existence de jQuery, mais jQuery ne respecte pas pleinement les promesses CommonJS / une spécification. Ensuite, comme vous pouvez le voir, la spécification ES 6 inclut la promesse.
La promesse est décrite dans MDN comme suit:
L'objet Promise est un indicateur indirect de la valeur de retour, qui peut ne pas être connu lorsque l'objet Promise est créé. Il vous permet de spécifier une méthode de traitement pour le succès ou la défaillance d'une opération asynchrone. Cela permet à la méthode asynchrone de renvoyer une valeur comme une méthode synchrone: la méthode asynchrone renvoie une valeur de retour d'origine
Le code suivant est un exemple de la section "Hellback Hell" implémenté par promesse. Le code ne semble pas très concis, mais il s'est considérablement amélioré par rapport aux rappels hiérarchiques traditionnels, et le code est plus maintenable et lisible.
getDirectories (). puis (fonction (dirs) {return getFiles (dirs [0]);}). puis (fonction (fichiers) {return getContent (fichiers [0]);}). puis (fonction (val) {console.log ('filename:', val.file); console.log (val.content);}); function getDirectries () {return new promest (function (résoudre, rejeter) {setTimeout (function () {résolve (['/ home / ben']);}, 1000);});} function getFiles (dir) {return new promed (function (résolve, reject) {setTimeout (function () {résolve ([dir + '/test1.txt', dir + '/test2.txt']);}, 1000);});} fonction getContent (file) {return new promed (function (résoudre, rejeter) {setTimeout (function ();});Générateur ES6
La mise en œuvre de la promesse n'est pas assez concise, nous avons toujours besoin d'un meilleur choix, le CO est l'un des choix. CO est un contrôleur de débit asynchrone basé sur le générateur. Avant de comprendre le CO, vous devez d'abord comprendre le générateur. Les étudiants qui connaissent C # doivent tous comprendre que la version C # 2.0 introduit le mot clé de rendement pour itérer le générateur. Le générateur ES 6 est similaire à C # et utilise également du sucre de syntaxe de rendement, et implémente une machine d'état en interne. Pour une utilisation spécifique, veuillez vous référer à la section Fonction du document MDN * et reportez-vous au blog Alloyteam Team pour une compréhension approfondie du générateur. Utilisez CO pour combiner intelligemment le générateur ES6 et ES6 promettent de rendre les appels asynchrones plus harmonieux.
co (function * () {var dirs = rendred getDirectries (); var files = rendet getFiles (dirs [0]); var tentatVal = rendement getContent (files [0]); console.log ('filename:', contenuval.file); console.log (contentVal.Content);});Le CO est très intelligent et son code central peut simplifier l'exemple suivant. L'idée générale est d'utiliser un générateur de traversée récursif jusqu'à ce que l'État soit terminé, bien sûr, CO fait plus.
Rungenerator (); Fonction * run () {var dirs = rendement getDirectries (); var fichiers = rendement getFiles (dirs [0]); var contentVal = rendement getContent (fichiers [0]); Console.log ('FileName:', ContentVal.File); console.log (contentVal.Content);} fonction rungenerator () {var gen = run (); function go (result) {if (result.done) return; result.value.then (function (r) {go (gen.next (r));}); } go (gen.next ());}ES7 Async / Await
Le générateur ES6 est vraiment bon, mais il est dommage que j'ai besoin du support d'une bibliothèque tierce. La bonne nouvelle est qu'Es 7 présentera le mot-clé async / attendu pour résoudre parfaitement le problème des appels asynchrones. Eh bien, .NET est une longueur d'avance, et .NET Framework 4.5 est déjà le premier à le soutenir.
Le futur code sera écrit comme ceci:
run (); fonction async run () {var dirs = attendre getDirectries (); var fichiers = attendre getFiles (dirs [0]); var contentVal = attendre getContent (fichiers [0]); Console.log ('FileName:', ContentVal.File); console.log (contentval.content);}en conclusion
De la méthode de programmation asynchrone de rappel classique à l'amélioration de la programmation asynchrone par la spécification ES6 Promise, au traitement élégant de cobombinant avec le générateur ES, et enfin la fin parfaite de l'asyn / Await, nous pouvons comprendre pourquoi Ecmascript a ces caractéristiques et les problèmes qui résolvent, et voir plus clairement le développement de Javascript AsyNccript AsyNcrict.