Comprender las promesas en Node.js

147

Por lo que he entendido, hay tres formas de llamar a un código asincrónico:

  1. Eventos, p. Ej. request.on("event", callback);
  2. Callbacks, p. Ej. fs.open(path, flags, mode, callback);
  3. Promesas

Encontré la biblioteca de promesa de nodo pero no la consigo.

¿Podría alguien explicar de qué se tratan las promesas y por qué debería usarlas?

Además, ¿por qué se eliminó de Node.js?

ajsie
fuente
Este artículo lo explica bastante bien. Cuando se trata de una implementación utilizable en node.js, eche un vistazo a Futures
Sean Kinsey
Aquí hay una gran serie que he usado para crear mi propia clase de promesa: Hagamos un marco: Promesas Aquí hay un video sobre jQuery diferido: blog.bigbinary.com/2011/09/03/jquery-deferred.html
Tom Winter

Respuestas:

91

Las promesas en node.js prometieron hacer algo de trabajo y luego tuvieron devoluciones de llamada separadas que se ejecutarían para el éxito y el fracaso, así como para manejar los tiempos de espera. Otra forma de pensar en las promesas en node.js era que eran emisores que solo podían emitir dos eventos: éxito y error.

Lo bueno de las promesas es que puedes combinarlas en cadenas de dependencia (haz la promesa C solo cuando se completen la promesa A y la promesa B).

Al eliminarlos del núcleo node.js, creó la posibilidad de construir módulos con diferentes implementaciones de promesas que pueden ubicarse en la parte superior del núcleo. Algunos de estos son promesa de nodo y futuros .

Paul Robinson
fuente
10
@weng No, no lo es.
Ivo Wetzel
98

Dado que esta pregunta todavía tiene muchas opiniones (como la mía), quería señalar que:

  1. La promesa de nodo me parece bastante muerta (la última confirmación fue hace aproximadamente 1 año) y casi no contiene pruebas.
  2. El módulo de futuros me parece muy hinchado y está mal documentado (y creo que las convenciones de nombres son simplemente malas)
  3. El mejor camino a seguir parece ser el marco q , que está activo y bien documentado.
enyo
fuente
9
Consulte también este github.com/medikoo/deferred , Q es uno de los primeros y definitivamente es inspiración para muchas implementaciones que aparecieron después, pero desafortunadamente es muy lento y demasiado "teórico" en algunas partes, no funciona bien con algunas escenarios del mundo real
Mariusz Nowak
Vería este video sobre las promesas de uno de los creadores de RSVP.js youtube.com/…
publicó el
23
Actualización 2014: bluebird es, con mucho, el más rápido y el que tiene las mejores capacidades de depuración en la actualidad.
Benjamin Gruenbaum
19

Una promesa es una "cosa" que representa los resultados "eventuales" de una operación, por así decirlo. El punto a tener en cuenta aquí es que, abstrae los detalles de cuándo sucede algo y le permite centrarse en lo que debería suceder después de que algo suceda. Esto dará como resultado un código limpio y fácil de mantener donde, en lugar de tener una devolución de llamada dentro de una devolución de llamada dentro de una devolución de llamada, su código se verá algo así:

 var request = new Promise(function(resolve, reject) {
   //do an ajax call here. or a database request or whatever.
   //depending on its results, either call resolve(value) or reject(error)
   //where value is the thing which the operation's successful execution returns and
   //error is the thing which the operation's failure returns.
 });

 request.then(function successHandler(result) {
   //do something with the result
 }, function failureHandler(error) {
  //handle
 });

La especificación de las promesas establece que una promesa

then

El método debe devolver una nueva promesa que se cumpla cuando finalice la devolución de llamada de SuccessHandler o la falla. Esto significa que puede encadenar promesas cuando tiene un conjunto de tareas asíncronas que deben realizarse y asegurarse de que la secuencia de operaciones está garantizada como si hubiera utilizado devoluciones de llamada. Entonces, en lugar de pasar una devolución de llamada dentro de una devolución de llamada dentro de una devolución de llamada, el código con promesas encadenadas se ve así:

var doStuff = firstAsyncFunction(url) {
                return new Promise(function(resolve, reject) {
                       $.ajax({
                        url: url,
                        success: function(data) {
                            resolve(data);
                        },
                        error: function(err) {
                             reject(err); 
                        } 
                  });
               };
doStuff
  .then(secondAsyncFunction) //returns a promise
  .then(thirdAsyncFunction); //returns a promise

Para saber más sobre las promesas y por qué son súper geniales, visite el blog de Domenic: http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

Hrishi
fuente
12

Este nuevo tutorial sobre Promesas del autor de PouchDB es probablemente el mejor que he visto en mi vida. Cubre sabiamente los errores clásicos de novato que muestran patrones de uso correctos e incluso algunos antipatrones que todavía se usan comúnmente, ¡incluso en otros tutoriales!

¡Disfrutar!

PD: No respondí algunas otras partes de esta pregunta, ya que han sido bien cubiertas por otros.

Tony O'Hagan
fuente
Mi única disculpa por esto es forzarte a leer humor al final del error avanzado # 4.
Tony O'Hagan
De hecho, el código en el tutorial que afirman ser un antipatrón necesita el anidamiento para el bucle y la condición, y no puede ser tan fácil como lo sugieren.
Bergi
El error avanzado n. ° 4 también se puede resolver utilizando un número mucho mayor de enfoques diferentes, consulte ¿Cómo accedo a resultados de promesas anteriores en una cadena .then ()? (el patrón de cierre que sugieren no parece ser muy popular).
Bergi
Creo que esta respuesta de solo enlace debería haber sido mejor un comentario. Ponga al menos los puntos principales de ese artículo en su respuesta aquí.
Bergi
7

Mike Taulty tiene una serie de videos , cada uno de ellos de menos de diez minutos de duración, que describe cómo funciona la biblioteca WinJS Promise.

Estos videos son bastante informativos, y Mike logra mostrar el poder de la API Promise con algunos ejemplos de código bien elegidos.

var twitterUrl = "http://search.twitter.com/search.json?q=windows";
var promise = WinJS.xhr({ url: twitterUrl });

 promise = promise.then(
     function (xhr) {
     },
     function (xhr) {
         // handle error
     });

El tratamiento de cómo se manejan las excepciones es particularmente bueno.

A pesar de las referencias de WinJs, esta es una serie de videos de interés general, porque la API Promise es ampliamente similar en todas sus implementaciones.

RSVP es una implementación ligera de Promise que supera el conjunto de pruebas Promise / A +. Me gusta bastante la API, porque es similar en estilo a la interfaz WinJS.

Actualización abr-2014

Por cierto, la biblioteca WinJS ahora es de código abierto .

Noel Abrahams
fuente
1
+1. Este es el primer ejemplo que he visto que tiene sentido para mí y es intuitivo de usar. De alguna manera mi cerebro no puede analizar toda la deferredsy resolve, y deferred.promise.then, y predefinir de promiseActionsen el popular Q documentación de la biblioteca. ¿Hay alguna posibilidad de que sepas algo tan sencillo para Node.js ?
Redsandro
1
@noel gracias por compartir el enlace anterior, es una excelente serie introductoria de promesas, y estoy de acuerdo en que los detalles de WinJS son irrelevantes ya que el enfoque / tema general es universal.
arcseldon
Buen ejemplo También arreglé su primer enlace que estaba muerto
stonedauwg
5

Otra ventaja de las promesas es que el manejo de errores y el lanzamiento y captura de excepciones es mucho mejor que tratar de manejar eso con devoluciones de llamada.

La biblioteca de bluebird implementa promesas y le brinda excelentes trazas largas de la pila, es muy rápida y advierte sobre errores no detectados. También es más rápido y usa menos memoria que las otras bibliotecas de promesa, de acuerdo con http://bluebirdjs.com/docs/benchmarks.html

llambda
fuente
4

¿Qué es exactamente una promesa?

Una promesa es simplemente un objeto que representa el resultado de una operación asíncrona. Una promesa puede ser en cualquiera de los siguientes 3 estados:

pendiente :: Este es el estado inicial, significa que la promesa no se cumple ni se rechaza.

cumplido :: Esto significa que la promesa se ha cumplido, significa que el valor representado por la promesa está listo para ser utilizado.

rechazado :: Esto significa que las operaciones fallaron y, por lo tanto, no pueden cumplir la promesa. Además de los estados, hay tres entidades importantes asociadas a las promesas que realmente necesitamos entender

  1. función ejecutor :: la función ejecutor define la operación asíncrona que debe realizarse y cuyo resultado está representado por la promesa. Comienza la ejecución tan pronto como se inicializa el objeto de promesa.

  2. resolve :: resolve es un parámetro pasado a la función ejecutor, y en caso de que el ejecutor se ejecute con éxito, esta resolución se llama pasar el resultado.

  3. rechazar :: rechazar es otro parámetro pasado a la función ejecutora, y se usa cuando falla la función ejecutora. La razón de la falla se puede pasar al rechazo.

Entonces, cada vez que creamos un objeto de promesa, tenemos que proporcionar Ejecutor, Resolver y Rechazar.

Referencia :: Promesas

Rishabh.IO
fuente
0

También he estado buscando promesas en node.js recientemente. Hasta la fecha, when.js parece ser el camino a seguir debido a su velocidad y uso de recursos, pero la documentación sobre q.js me dio una mejor comprensión. Entonces use when.js pero los documentos q.js para entender el tema.

Del archivo léame de q.js en github:

Si una función no puede devolver un valor o lanzar una excepción sin bloquear, puede devolver una promesa. Una promesa es un objeto que representa el valor de retorno o la excepción lanzada que la función puede proporcionar eventualmente. Una promesa también se puede utilizar como proxy para que un objeto remoto supere la latencia.

Andrew Roberts
fuente
0

El objeto de promesa representa la finalización o falla de una operación asincrónica.

Entonces, para implementar una promesa, necesita dos partes:

1. Creando promesa:

El constructor de la promesa acepta una función llamada ejecutor que tiene 2 parámetros resolver y rechazar.

function example(){
   return new Promise (function(resolve , reject){   //return promise object
      if(success){
         resolve('success');  //onFullfiled
      }else{
         reject('error');     //onRejected
      }
   })
}

2. Promesa de manejo:

El objeto de promesa tiene 3 métodos para manejar objetos de promesa: -

1.Promise.prototype.catch (onRejected)

2.Promise.prototype.then (onFullfiled)

3.Promise.prototype.finally (onFullfiled, onRejected)

example.then((data) =>{
  //handles resolved data
  console.log(data); //prints success     
}).catch((err) => {
  //handles rejected error 
  console.log(err);  //prints error
})
Pavneet Kaur
fuente