javascript una ¿No son promesas sólo devoluciones de llamada?




promesas javascript (6)

Además de las otras respuestas, la sintaxis de ES2015 combina a la perfección con las promesas, reduciendo aún más el código de repetición:

// Sequentially:
api1()
  .then(r1 => api2(r1))
  .then(r2 => api3(r2))
  .then(r3 => {
      // Done
  });

// Parallel:
Promise.all([
    api1(),
    api2(),
    api3()
]).then(([r1, r2, r3]) => {
    // Done
});

He estado desarrollando JavaScript durante algunos años y no entiendo el alboroto de las promesas.

Parece que todo lo que hago es cambiar:

api(function(result){
    api2(function(result2){
        api3(function(result3){
             // do work
        });
    });
});

Que 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í, de repente tampoco es mágicamente "plano". Por no hablar de tener que convertir las cosas en promesas.

Entonces, ¿cuál es el gran escándalo de las promesas aquí?


No hay promesas que sean envueltas en las devoluciones de llamada

ejemplo Puede usar promesas nativas de javascript con el nodo 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

Además de las increíbles respuestas anteriores, se pueden agregar 2 puntos más:

1. Diferencia semántica:

Las promesas ya pueden ser resueltas sobre la creación. Esto significa que garantizan condiciones en lugar de eventos . Si ya están resueltos, la función resuelta pasada a ella aún se llama.

Por el contrario, las devoluciones de llamada manejan eventos. Por lo tanto, si el evento en el que está interesado ha ocurrido antes de que se registre la devolución de llamada, no se invoca 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á listo para ejecutarse.

Consulte el bucle de eventos de Javascript para obtener una explicación.

Con Promesas , el control reside en el programa de llamada. El método .then () se puede llamar en cualquier momento si almacenamos el objeto de promesa.


Sí, las promesas son devoluciones de llamada asíncronas. 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 repetitivo propenso a errores.

Entonces, ¿cuál es la idea principal?

Las promesas son objetos que representan el resultado de un cálculo único (asíncrono). Se resuelven a ese resultado solo una vez. Hay algunas cosas que esto significa:

Las promesas implementan un patrón de observador:

  • No es necesario conocer las devoluciones de llamada que utilizarán el valor antes de que finalice la tarea.
  • En lugar de esperar devoluciones de llamada como argumentos a sus funciones, puede return fácilmente un objeto Promise
  • La promesa almacenará el valor, y puede agregar de manera transparente una devolución de llamada cuando lo desee. Se llamará cuando el resultado esté disponible. La "transparencia" implica que cuando tiene una promesa y le agrega una devolución de llamada, no hace una diferencia en su código si el resultado ha llegado todavía: la API y los contratos son los mismos, lo que simplifica mucho el almacenamiento en caché y la memoria.
  • Puede agregar múltiples devoluciones de llamada fácilmente

Las promesas son imposibles de cambiar ( monádicas , si quieres):

  • Si necesita transformar el valor que representa una promesa, asigne una función de transformación sobre la promesa y recupere una nueva promesa que represente el resultado transformado. No puede obtener sincrónicamente el valor para usarlo de alguna manera, pero puede elevar fácilmente la transformación en el contexto de promesa. No hay devoluciones de llamada repetitivo.
  • Si desea encadenar dos tareas asíncronas, puede usar el método .then() . El primer resultado requerirá una devolución de llamada y devuelve una promesa para el resultado de la promesa de que se devuelve la devolución de llamada.

¿Suena complicado? Tiempo para 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 mágicamente, 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 comprenderlo, aquí hay una promesa más básica: lib en pocas líneas .

¿Cuál es el gran alboroto de las promesas?

La abstracción de Promise permite una mejor composibilidad de las funciones. Por ejemplo, al lado de then para el encadenamiento, la función all crea una promesa para el resultado combinado de múltiples promesas de espera paralelas.

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, de modo que no necesita 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 dedicado para todas las excepciones ocurridas.

Por no hablar de tener que convertir las cosas en promesas.

Eso es bastante trivial en realidad con bibliotecas con buenas promesas, consulte ¿Cómo convierto una API de devolución de llamada existente en promesas?


Además de las respuestas ya establecidas, con las funciones de flecha de ES6 Las promesas cambian de una pequeña enana azul modestamente brillante a 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 anónimas de envoltura:

api().then(api2).then(api3).then(r3 => console.log(r3))

Y finalmente, si desea alcanzar un nivel de agujero negro supermasivo, se pueden esperar las promesas:

async function callApis() {
    let api1Result = await api();
    let api2Result = await api2(api1Result);
    let api3Result = await api3(api2Result);

    return api3Result;
}

Las promesas no son devoluciones de llamada. Una promesa representa el resultado futuro de una operación asíncrona . Por supuesto, al escribirlos como lo haces, obtienes pocos beneficios. Pero si los escribe de la forma en que están destinados a ser utilizados, puede escribir código asíncrono de una manera que se asemeja al código síncrono y que 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 mucho más legible.

Pero, este no es el final. Vamos a descubrir los verdaderos beneficios: ¿Qué sucede si desea verificar si hay algún error en alguno de los pasos? Sería un infierno hacerlo con devoluciones de llamada, pero con promesas, es un pedazo de pastel:

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
});

Más o menos lo mismo que un bloque try { ... } catch .

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é pasaría si esas 3 llamadas a api , api2 , api3 pudieran ejecutarse simultáneamente (por ejemplo, si fueran llamadas AJAX) pero tuvieras que esperar a las tres? Sin promesas, deberías crear algún tipo de contador. Con las promesas, usar la notación ES6, es otro pedazo de pastel y bastante limpio:

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 Promesas bajo una nueva luz ahora.





bluebird