He estado desarrollando JavaScript durante algunos años y no entiendo el alboroto sobre las promesas en absoluto.
Parece que todo lo que hago es cambiar:
api(function(result){
api2(function(result2){
api3(function(result3){
// do work
});
});
});
Para lo cual podría usar una biblioteca como async de todos modos, con algo como:
api().then(function(result){
api2().then(function(result2){
api3().then(function(result3){
// do work
});
});
});
Que es más código y menos legible. No gané nada aquí, tampoco es mágicamente 'plano' de repente. Sin mencionar tener que convertir las cosas en promesas.
Entonces, ¿cuál es el gran alboroto por las promesas aquí?
Respuestas:
Las promesas no son devoluciones de llamada. Una promesa representa el resultado futuro de una operación asincrónica . Por supuesto, al escribirlos de la manera que lo haces, obtienes pocos beneficios. Pero si los escribe de la forma en que deben usarse, puede escribir código asincrónico de una manera que se parezca a un código síncrono y sea mucho más fácil de seguir:
Ciertamente, no mucho menos código, pero mucho más legible.
Pero, este no es el final. Descubramos los verdaderos beneficios: ¿Qué sucede si desea verificar cualquier error en alguno de los pasos? Sería un infierno hacerlo con devoluciones de llamada, pero con promesas, es pan comido:
Más o menos lo mismo que un
try { ... } catch
bloque.Aun mejor:
Y aún mejor: ¿Qué pasa si esas llamadas a 3
api
,api2
,api3
podían ejecutar de forma simultánea (por ejemplo, si fueran llamadas AJAX) pero necesitan que esperar a los tres? Sin promesas, deberías tener que crear algún tipo de contador. Con promesas, usar la notación ES6 es otro pedazo de pastel y bastante bueno:Espero que veas las promesas bajo una nueva luz ahora.
fuente
api2
yapi3
? ¿se llamaría al último.then
una vez que se completen esas operaciones asincrónicas?Sí, las promesas son devoluciones de llamada asincrónicas. No pueden hacer nada que las devoluciones de llamada no puedan hacer, y usted enfrenta los mismos problemas con la asincronía que con las devoluciones de llamada simples.
Sin embargo, las promesas son más que simples devoluciones de llamada. Son una abstracción muy poderosa, permiten un código funcional más limpio y mejor con menos repeticiones propensas a errores.
Las promesas son objetos que representan el resultado de un cálculo único (asíncrono). Ellos resuelven a ese resultado sólo una vez. Hay algunas cosas que significa esto:
Las promesas implementan un patrón de observación:
return
un objeto PromiseLas promesas son encadenables ( monádicas , si quieres ):
.then()
método. Se necesitará una devolución de llamada para ser llamada con el primer resultado, y devuelve una promesa para el resultado de la promesa de que la devolución de llamada regresa.¿Suena complicado? Tiempo para un ejemplo de código.
El aplanamiento no viene mágicamente, pero puedes hacerlo fácilmente. Para su ejemplo muy anidado, el equivalente (cercano) sería
Si ver el código de estos métodos ayuda a comprender, aquí hay una promesa más básica en pocas líneas .
La abstracción de Promise permite una mejor composibilidad de funciones. Por ejemplo, junto a
then
encadenar, laall
función crea una promesa para el resultado combinado de múltiples promesas de espera paralela.Por último, pero no menos importante, las promesas vienen con un manejo integrado de errores. El resultado del cálculo podría ser que la promesa se cumple con un valor o se rechaza con un motivo. Todas las funciones de composición manejan esto automáticamente y propagan errores en las cadenas de promesa, para que no tenga que preocuparse explícitamente en todas partes, en contraste con una implementación de devolución de llamada simple. Al final, puede agregar una devolución de llamada de error dedicada para todas las excepciones ocurridas.
Eso es bastante trivial en realidad con buenas bibliotecas de promesa, vea ¿Cómo convierto una API de devolución de llamada existente en promesas?
fuente
.then(console.log)
, ya que console.log depende del contexto de la consola. De esta forma, provocará un error de invocación ilegal. Useconsole.log.bind(console)
ox => console.log(x)
para enlazar contexto.console
métodos ya están vinculados. Y, por supuesto, solo dije que ambos anidamientos tienen exactamente el mismo comportamiento, no que ninguno de ellos funcionaría :-PAdemás de las respuestas ya establecidas, con funciones ES6 flecha promesas de convertir una pequeña enana azul brillante modestamente recta en una gigante roja. Eso está a punto de colapsar en una supernova:
Como señaló oligofren , sin argumentos entre las llamadas de API, no necesita las funciones de contenedor anónimo en absoluto:
Y, por último, si quieres alcanzar un nivel de agujero negro supermasivo, puedes esperar promesas:
fuente
apiX
métodos, que también podría omitir por completo las funciones de dirección:api().then(api2).then(api3).then(r3 => console.log(r3))
.Además de las impresionantes respuestas anteriores, se pueden agregar 2 puntos más:
1. Diferencia semántica:
Las promesas pueden estar resueltas en el momento de la creación. Esto significa que garantizan condiciones en lugar de eventos . Si ya están resueltos, la función resuelta que se le pasa todavía se llama.
Por el contrario, las devoluciones de llamada manejan eventos. Por lo tanto, si el evento que le interesa ha sucedido antes de que se registre la devolución de llamada, no se llama a la devolución de llamada.
2. Inversión de control
Las devoluciones de llamada implican la inversión del control. Cuando registra una función de devolución de llamada con cualquier API, el tiempo de ejecución de Javascript almacena la función de devolución de llamada y la llama desde el bucle de eventos una vez que está lista para ejecutarse.
Consulte el bucle de eventos de Javascript para obtener una explicación.
Con Promesas , el control reside en el programa de llamadas. Se puede llamar al método .then () en cualquier momento si almacenamos el objeto de promesa.
fuente
Además de las otras respuestas, la sintaxis ES2015 combina a la perfección con las promesas, reduciendo aún más el código repetitivo:
fuente
Las promesas no son devoluciones de llamada, ambas son expresiones idiomáticas de programación que facilitan la programación asíncrona. El uso de una programación de estilo asíncrono / en espera utilizando corutinas o generadores que devuelven promesas podría considerarse un tercer idioma. Una comparación de estos modismos en diferentes lenguajes de programación (incluido Javascript) está aquí: https://github.com/KjellSchubert/promise-future-task
fuente
No, en absoluto.
Las devoluciones de llamada son simplemente funciones en JavaScript que deben llamarse y luego ejecutarse después de que la ejecución de otra función haya finalizado. Entonces, ¿cómo sucede?
En realidad, en JavaScript, las funciones se consideran en sí mismas como objetos y, por lo tanto, como todos los demás objetos, incluso las funciones se pueden enviar como argumentos a otras funciones . El caso de uso más común y genérico en el que uno puede pensar es la función setTimeout () en JavaScript.
Las promesas no son más que un enfoque mucho más improvisado de manejo y estructuración de código asincrónico en comparación con hacer lo mismo con las devoluciones de llamada.
La promesa recibe dos devoluciones de llamada en la función de constructor: resolver y rechazar. Estas devoluciones de llamada dentro de las promesas nos proporcionan un control detallado sobre el manejo de errores y los casos de éxito. La devolución de llamada de resolución se usa cuando la ejecución de la promesa se realizó con éxito y la devolución de llamada de rechazo se usa para manejar los casos de error.
fuente
No hay promesas son solo envoltorios en devoluciones de llamadas
ejemplo Puede usar las promesas nativas de JavaScript con el nodo js
fuente
Las Promesas de JavaScript en realidad usan funciones de devolución de llamada para determinar qué hacer después de que una Promesa se haya resuelto o rechazado, por lo tanto, ambas no son fundamentalmente diferentes. La idea principal detrás de Promises es tomar devoluciones de llamada, especialmente devoluciones de llamada anidadas donde desea realizar un tipo de acciones, pero sería más legible.
fuente
Resumen de promesas:
En JS podemos envolver operaciones asincrónicas (por ejemplo, llamadas a bases de datos, llamadas AJAX) en promesas. Por lo general, queremos ejecutar una lógica adicional en los datos recuperados. Las promesas de JS tienen funciones de controlador que procesan el resultado de las operaciones asincrónicas. Las funciones del controlador pueden incluso tener otras operaciones asincrónicas dentro de ellas que podrían depender del valor de las operaciones asincrónicas anteriores.
Una promesa siempre tiene de los siguientes 3 estados:
Una promesa pendiente puede resolverse / cumplirse o rechazarse con un valor. Luego se llaman los siguientes métodos de controlador que toman las devoluciones de llamada como argumentos:
Promise.prototype.then()
: Cuando se resuelve la promesa, se llamará al argumento de devolución de llamada de esta función.Promise.prototype.catch()
: Cuando se rechaza la promesa, se llamará al argumento de devolución de llamada de esta función.Aunque las habilidades de métodos anteriores obtienen argumentos de devolución de llamada, son muy superiores a usar solo devoluciones de llamada. Aquí hay un ejemplo que aclarará mucho:
Ejemplo
then
método y el valor resuelto se pasa como argumento de la devolución de llamadacatch
método y el valor rechazado se pasa como argumentocatch
ythen
devuelven promesas, por eso podemos encadenarlos. Envuelven cualquier valor devueltoPromise.resolve
y cualquier valor arrojado (usando lathrow
palabra clave) enPromise.reject
. Por lo tanto, cualquier valor devuelto se transforma en una promesa y en esta promesa podemos llamar nuevamente a una función de controlador.catch
método maneja todos los errores que ocurrieron antes delcatch
controlador.fuente