Infierno de devolución de llamada
Para los programadores de JavaScript, el manejo de devoluciones de llamada es hogareña, pero manejar devoluciones de llamada con niveles demasiado profundos no es tan hermoso. El siguiente fragmento de código de muestra utiliza devoluciones de llamada de tres capas y luego repone el cerebro para obtener más capas de escenas. Es simplemente agrio. Este es el legendario infierno de devolución de llamada.
getDirectorios (function (dirs) {getFiles (dirs [0], function (files) {getContent (files [0], function (file, content) {console.log ('filename:', file); console.log (content);});});}); function getDirectorials (callback) {setTimeOut (function () {callback (['/home/ben']);}, 1000);} function getFiles (dir, callback) {setTimeout (function () {callback ([dir + '/test1.txt', dir + '/test2.txt']);}, 1000)} getContent (fileback) (fileback) (fileback). setTimeOut (function () {llamado (archivo, 'contenido');}, 1000)}Solución
Hay muchas soluciones asíncronas en el ecosistema que pueden manejar el problema del infierno de devolución de llamada, como Bluebird, Q, etc. Este artículo se centra en el soporte para la programación asincrónica en la especificación Ecmascript 6/7.
ES6 Promesa
Promise es una solución para la programación asincrónica y una herramienta poderosa para resolver el problema del infierno de devolución de llamada.
La promesa fue aceptada convencional en el ecosistema de JavaScript en 2007 cuando el marco de Dojo agregó la funcionalidad de Deferred. Con la popularidad de Dojo. Deferred, en 2009, Kris Zyp propuso las promesas CommonJS/A especificaciones. Posteriormente, una gran cantidad de implementaciones de promesa aparecieron en el ecosistema, incluidos Q.JS, Futuresjs, etc. Por supuesto, la popularidad de la promesa se debe en gran medida a la existencia de jQuery, pero JQuery no cumple completamente con las promesas comunesjs/una especificación. Luego, como puede ver, la especificación ES 6 incluye promesa.
La promesa se describe en MDN de la siguiente manera:
El objeto de promesa es un proxy para el valor de retorno, que puede no ser conocido cuando se crea el objeto de promesa. Le permite especificar un método de manejo para el éxito o la falla de una operación asincrónica. Esto permite que el método asincrónico devuelva un valor como un método sincrónico: el método asíncrono devuelve un valor de retorno original
El siguiente código es un ejemplo en la sección "Infierno de devolución de llamada" implementada a través de Promise. El código no parece muy conciso, pero ha mejorado significativamente en comparación con las devoluciones de llamada jerárquicas tradicionales, y el código es más mantenible y legible.
getDirectorories (). entonces (function (dirs) {return getFiles (dirs [0]);}). entonces (function (files) {return getContent (archivos [0]);}). entonces (function (val) {console.log ('filename:', val.file); console.log (val.content);}); function getDirectorials () {return new Promise (function (resolve, rechazar) {setTimeOut (function () {resolve (['/home/ben']);}, 1000);});} function getFiles (dir) {return new promise (function (resolve, rechazar) {settimeOut (function () {resolve (dir + '' /test1.txt ', dir +' '']; }, 1000);});} function getContent (file) {return new promise (function (resolve, rechazar) {setTimeOut (function () {resolve ({file: file, content: 'content'});}, 1000);});};Generador ES6
La implementación de la promesa no es lo suficientemente simple, todavía necesitamos una mejor opción, y CO es una de las opciones. CO es un controlador de flujo asíncrono basado en el generador. Antes de comprender el CO, primero debe comprender al generador. Todos los estudiantes que están familiarizados con C# deben comprender que la versión C# 2.0 presenta la palabra clave de rendimiento para iterar el generador. El generador ES 6 es similar a C#, y también utiliza azúcar de sintaxis de rendimiento e implementa una máquina de estado internamente. Para un uso específico, consulte la sección de la función del documento MDN* y consulte el blog del equipo AlloyTeam para obtener una comprensión en profundidad del generador. Use CO para combinar inteligentemente el generador ES6 y ES6 promete hacer que las llamadas asíncronas sean más armoniosas.
CO (function* () {var dirs = rendimiento getDirectorios (); var files = rendimiento getFiles (dirs [0]); var contentVal = rendimiento getContent (archivos [0]); console.log ('filename:', contentval.file); console.log (contentVal.content);});CO es muy inteligente, y su código central puede simplificar el siguiente ejemplo. La idea general es utilizar el generador de recorrido recursivo hasta que el estado se complete, por supuesto, CO hace más.
runGenerator (); function* run () {var dirs = rendimiento getDirectorios (); VAR archivos = rendimiento getFiles (dirs [0]); var contentVal = rendimiento getContent (archivos [0]); console.log ('FileName:', contentVal.file); console.log (contentVal.content);} function runGenerator () {var gen = run (); función go (resultado) {if (result.done) return; result.value.then (function (r) {go (gen.next (r));}); } go (gen.next ());}ES7 async/espera
El generador ES6 es realmente bueno, pero es una pena que necesite el soporte de una biblioteca de terceros. La buena noticia es que ES 7 presentará la palabra clave Async/espera para resolver perfectamente el problema de las llamadas asíncronas. Bueno, .NET está un paso por delante, y .NET Framework 4.5 ya es el primero en admitirlo.
El código futuro se escribirá así:
run (); function async run () {var dirs = await getDirectorios (); VAR archivos = ALEA GETFILES (DIRS [0]); var contentval = await getContent (archivos [0]); console.log ('FileName:', contentVal.file); console.log (contentval.content);}en conclusión
Desde el clásico método de programación asincrónica de devolución de llamada, hasta la mejora de la programación asincrónica por la especificación ES6 Promise, hasta el procesamiento elegante de CO-Combined with ES Generator, y finalmente la finalización perfecta de ES7 Async/Invm., Podemos entender por qué ECMAScript tiene estas características y qué problemas resuelven, y ver más claramente el desarrollo del programa JavaScript asynchronus.