He estado desarrollando JavaScript durante algunos años y no entiendo en absoluto el alboroto por las promesas.
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
});
});
});
Cuál es más código y menos legible. No gané nada aquí, tampoco es mágicamente 'plano' de repente. Por no hablar de tener que convertir las cosas en promesas.
Entonces, ¿cuál es el gran alboroto sobre las promesas aquí?
Las promesas no son devoluciones de llamada. Una promesa representa el resultado futuro de una operación asincrónica . Por supuesto, si los escribe de la manera que lo hace, obtiene pocos beneficios. Pero si los escribe de la forma en que deben usarse, puede escribir código asincrónico de una manera que se asemeje al código sincrónico y sea mucho más fácil de seguir:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
});
Ciertamente, no mucho menos código, pero sí mucho más legible.
Pero, este no es el final. Descubramos los verdaderos beneficios: ¿Qué pasaría si quisiera verificar si hay algún error en cualquiera de los pasos? Sería un infierno hacerlo con devoluciones de llamada, pero con promesas, es pan comido:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
});
Casi lo mismo que un try { ... } catch
bloque.
Aun mejor:
api().then(function(result){
return api2();
}).then(function(result2){
return api3();
}).then(function(result3){
// do work
}).catch(function(error) {
//handle any error that may occur before this point
}).then(function() {
//do something whether there was an error or not
//like hiding an spinner if you were performing an AJAX request.
});
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ía tener que crear algún tipo de contador. Con promesas, usar la notación ES6 es otro pedazo de pastel y bastante bueno:
Promise.all([api(), api2(), api3()]).then(function(result) {
//do work. result is an array contains the values of the three fulfilled promises.
}).catch(function(error) {
//handle the error. At least one of the promises rejected.
});
Espero que veas Promises bajo una nueva luz ahora.
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 devoluciones de llamada. Son una abstracción muy poderosa, permiten un código más limpio y mejor, funcional con un texto repetitivo menos propenso a errores.
Entonces, ¿cuál es la idea principal?
Las promesas son objetos que representan el resultado de un único cálculo (asincrónico). Ellos resuelven a ese resultado sólo una vez. Hay algunas cosas que significa esto:
Las promesas implementan un patrón de observador:
return
un objeto PromiseLas promesas son encadenables ( monádicas , si quieres ):
.then()
método. Se necesitará una devolución de llamada para que se llame con el primer resultado y devuelve una promesa para el resultado de la promesa de que la devolución de llamada devuelve.¿Suena complicado? Es hora de un ejemplo de código.
var p1 = api1(); // returning a promise
var p3 = p1.then(function(api1Result) {
var p2 = api2(); // returning a promise
return p2; // The result of p2 …
}); // … becomes the result of p3
// So it does not make a difference whether you write
api1().then(function(api1Result) {
return api2().then(console.log)
})
// or the flattened version
api1().then(function(api1Result) {
return api2();
}).then(console.log)
El aplanamiento no viene por arte de magia, pero puedes hacerlo fácilmente. Para su ejemplo fuertemente anidado, el equivalente (cercano) sería
api1().then(api2).then(api3).then(/* do-work-callback */);
Si ver el código de estos métodos ayuda a comprender, aquí hay una biblioteca de promesas más básica en unas pocas líneas .
¿Cuál es el gran alboroto sobre las promesas?
La abstracción Promise permite una mejor componibilidad de funciones. Por ejemplo, junto a then
para encadenamiento, la all
función crea una promesa para el resultado combinado de múltiples promesas de espera en paralelo.
Por último, pero no menos importante, las promesas vienen con un manejo de errores integrado. El resultado del cálculo podría ser que la promesa se cumple con un valor o se rechaza con una razón. Todas las funciones de composición manejan esto automáticamente y propagan errores en las cadenas de promesas, por lo que no necesita preocuparse explícitamente por todas partes, a diferencia de 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.
Por no hablar de tener que convertir las cosas en promesas.
En realidad, eso es bastante trivial con las bibliotecas de buenas promesas, consulte ¿Cómo convierto una API de devolución de llamada existente en promesas?
Ademá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:
api().then(result => api2()).then(result2 => api3()).then(result3 => console.log(result3))
Como señaló oligofren , sin argumentos entre las llamadas a la API, no necesita las funciones de contenedor anónimas en absoluto:
api().then(api2).then(api3).then(r3 => console.log(r3))
Y finalmente, si quieres alcanzar un nivel de agujero negro supermasivo, puedes esperar promesas:
async function callApis() {
let api1Result = await api();
let api2Result = await api2(api1Result);
let api3Result = await api3(api2Result);
return api3Result;
}
Además de las impresionantes respuestas anteriores, se pueden agregar 2 puntos más:
1. Diferencia semántica:
Las promesas pueden estar ya resueltas en el momento de la creación. Esto significa que garantizan condiciones más que eventos . Si ya están resueltos, la función resuelta que se le ha pasado todavía se llama.
Por el contrario, las devoluciones de llamada manejan eventos. Por lo tanto, si el evento que le interesa ocurrió antes de que se registrara 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 de 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 Promises , el control reside en el programa de llamadas. El método .then () se puede llamar en cualquier momento si almacenamos el objeto de promesa.
Además de las otras respuestas, la sintaxis de ES2015 se combina a la perfección con las promesas, lo que reduce aún más el código estándar:
// Sequentially:
api1()
.then(r1 => api2(r1))
.then(r2 => api3(r2))
.then(r3 => {
// Done
});
// Parallel:
Promise.all([
api1(),
api2(),
api3()
]).then(([r1, r2, r3]) => {
// Done
});
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 pueden enviarse como argumentos a otras funciones . El caso de uso más común y genérico que se 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 constructora: resolver y rechazar. Estas devoluciones de llamada internas nos brindan 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ó correctamente y la devolución de llamada de rechazo se usa para manejar los casos de error.
Las promesas no son devoluciones de llamada, ambos son modismos de programación que facilitan la programación asincrónica. El uso de un estilo de programación asíncrono / en espera usando corrutinas o generadores que devuelven promesas podría considerarse un tercer idioma de este tipo. Una comparación de estos modismos en diferentes lenguajes de programación (incluido Javascript) está aquí: https://github.com/KjellSchubert/promise-future-task
Ninguna promesa es simplemente envoltorio en devoluciones de llamada
ejemplo Puede usar promesas nativas de JavaScript con node js
my cloud 9 code link : https://ide.c9.io/adx2803/native-promises-in-node
/**
* Created by dixit-lab on 20/6/16.
*/
var express = require('express');
var request = require('request'); //Simplified HTTP request client.
var app = express();
function promisify(url) {
return new Promise(function (resolve, reject) {
request.get(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body);
}
else {
reject(error);
}
})
});
}
//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
//get the post with post id 100
promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
var obj = JSON.parse(result);
return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
})
.catch(function (e) {
console.log(e);
})
.then(function (result) {
res.end(result);
}
)
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
//run webservice on browser : http://localhost:8081/listAlbums
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 recibir devoluciones de llamada, especialmente devoluciones de llamada anidadas donde desea realizar una especie de acciones, pero sería más legible.
En JS podemos envolver operaciones asincrónicas (por ejemplo, llamadas a bases de datos, llamadas AJAX) en promesas. Por lo general, queremos ejecutar alguna 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 3 estados siguientes:
Una promesa pendiente se puede resolver / cumplir o rechazar con un valor. Luego, se llaman los siguientes métodos de controlador que toman devoluciones de llamada como argumentos:
Promise.prototype.then()
: Cuando se resuelva 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 la habilidad de los métodos anteriores obtiene argumentos de devolución de llamada, son muy superiores a usar solo devoluciones de llamada, aquí hay un ejemplo que aclarará mucho:
function createProm(resolveVal, rejectVal) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
console.log("Resolved");
resolve(resolveVal);
} else {
console.log("Rejected");
reject(rejectVal);
}
}, 1000);
});
}
createProm(1, 2)
.then((resVal) => {
console.log(resVal);
return resVal + 1;
})
.then((resVal) => {
console.log(resVal);
return resVal + 2;
})
.catch((rejectVal) => {
console.log(rejectVal);
return rejectVal + 1;
})
.then((resVal) => {
console.log(resVal);
})
.finally(() => {
console.log("Promise done");
});
then
, se llama al primer método y el valor resuelto se pasa como argumento de la devolución de llamada.catch
método y el valor rechazado se pasa como argumentocatch
y then
devuelven promesas, por eso podemos encadenarlos. Envuelven cualquier valor devuelto Promise.resolve
y cualquier valor arrojado (utilizando la throw
palabra clave) Promise.reject
. Entonces, cualquier valor devuelto se transforma en una promesa y en esta promesa podemos volver a llamar a una función de controlador.catch
método maneja todos los errores que han ocurrido antes que el catch
controlador.La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Captura de pantalla del video de Facebook Para aquellos de ustedes que pueden ser demasiado jóvenes para saber esto, antes de que Ice-T fuera una gran estrella en Ley y orden: Unidad de víctimas especiales, era uno de los mejores raperos gangsta de Los Ángeles de todos los tiempos. De hecho, estaba haciendo gangsta rap antes que N.
Imagen a través de WHAS 11 Algunas cosas realmente podrían tener "carga racial" sin ser racistas. Pero en los principales medios de comunicación, el primero suele ser un código para el segundo.
Foto: Sony Taraji P. Henson, experta tanto en reacciones cáusticas como en expresiones con los ojos húmedos de abrumador conflicto interno, es una actriz dinámica.
Foto: Ronald Martinez / Getty El grandote de los Spurs, LaMarcus Aldridge está teniendo quizás la temporada más eficiente de su carrera mientras reemplaza a Kawhi Leonard como el jugador principal de San Antonio. Mientras que los Warriors y los Rockets están en una carrera armamentista para ver quién puede disparar 100 triples en un juego primero, los Spurs están escondidos detrás de Houston.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.