w3schools then promises promesas nodejs ejemplo anidadas javascript node.js promise q

javascript - then - Promesas: ¿se ejecuta.done() siempre incluso si.catch() es?



promises javascript w3schools (3)

Mi problema de Promesa

Soy nuevo en Promises y he estado leyendo la Documentación Q , donde dice:

Cuando llegue al final de una cadena de promesas, debe devolver la última promesa o finalizar la cadena.

He definido una Promesa en mi código la forma Q.Promise , con los siguientes console.log s para cerrar la sesión de un seguimiento de ejecución:

function foo(){ return Q.Promise(function(resolve, reject) { doSomething() .then(function() { console.log(''1''); return doSomething1(); }) .then(function() { console.log(''2''); return doSomething2(); }) .then(function() { console.log(''3''); return doSomething3(); }) .catch(function(err) { console.log(''catch!!''); reject(err); }) .done(function() { console.log(''done!!''); resolve(); }); }); }

En caso de que cada doSomethingN() ejecute correctamente, todo funciona según lo previsto y obtengo el rastro esperado:

1 2 3 done!!

Pero en caso de que falle alguno de los doSomethingN() :

foo() funciona correctamente, porque la devolución de llamada de la función de error es la que se ejecuta cada vez que se produce un reject(err) :

foo().then(function() { /* */ }, function(err) { /* this runs! */ });

Y obtengo el siguiente rastro (es decir, cuando doSomething1() falla):

1 catch!! done!!

Mi pregunta

Lo que pensé al principio fue lo siguiente:

De acuerdo, manejemos el éxito y el fracaso del encadenamiento en ambos .done() : .done() y .catch() . Si todo va bien, la devolución de llamada de .done() se ejecutará y la promesa se resolverá . En caso de que haya un error en algún momento, se .catch() la devolución de llamada de .catch() y se rechazará la promesa, y debido a eso, done() no se ejecutará.

Creo que me falta algo acerca de cómo funciona el .done() ... porque al echar un vistazo a mi rastreo de registro, me di cuenta de que .done() parece estar ejecutándose siempre, si hay un error y .catch() se ejecuta o no, y eso es lo que no esperaba.

Entonces, después de eso, .done() la devolución de llamada de .done() y ahora foo() :

  • funciona si hay un error durante la ejecución de la cadena
  • no funciona si todo funciona correctamente

¿Qué debería reconsiderar y cómo podría / debería hacer que funcione?


Deberías considerar hacer esto:

function foo() { // Calling .then() on a promise still return a promise. // You don''t need Q.Promise here return doSomething() .then(function(doSomethingResult) { console.log(''1''); return doSomething1(); }) .then(function(doSomething1Result) { console.log(''2''); return doSomething2(); }) .then(function(doSomething2Result) { console.log(''3''); return doSomething3(); }); } foo() .then(function(fooResult) { console.log(fooResult); // fooResult should be what is returned by doSomething3() }) .catch(function(err) { console.error(err); // Can be thrown by any }) .done(function() { console.log(''I am always executed! error or success''); });

Si desea devolver una promesa, en la mayoría de los casos no tiene mucho sentido utilizar catch (a menos que desee recuperar posibles errores). Nunca tiene sentido usar done en un método que devuelve una promesa. Prefieres utilizar estos métodos al final de la cadena.

Tenga en cuenta que doSomethingX() puede devolver un valor, o una promesa, funcionará de la misma manera.


Puedes hacerlo funcionar resolviendo la promesa en tu última devolución de llamada.

function foo(){ return doSomething() .then(function() { console.log(''1''); return doSomething1(); }) .then(function() { console.log(''2''); return doSomething2(); }) .then(function() { console.log(''3''); return doSomething3(); }) }

Considera usar bluebird para las promesas. Tiene muchas funciones útiles en comparación con cualquier otra biblioteca de promesas. Puede que le resulte difícil comenzar, pero una vez que lo agarra lo va a encantar.


catch(cb) es solo un alias para then(null, cb) , y realmente ha corregido un error en catch , por lo que el flujo naturalmente se convirtió en éxito .

Si solo quiere decorar el error en la captura, debe volver a generar el error después, por ejemplo, un recorrido correcto puede verse como:

catch(function (err) { console.log(err); throw err; });

Aún así tu ejemplo no tiene mucho sentido. Nunca deberías usar " done cuando devuelves una promesa. Si desea resolver una promesa inicializada con cadenas de promesas creadas internamente, debe resolverlas como:

resolve(doSomething() .then(function() { console.log(''1''); return doSomething1(); }) .... .then(function() { console.log(''N''); return doSomethingN(); }));

No es necesario el manejo interno de errores, déjelo al consumidor de la promesa que devuelve.

Y otro punto. Si al crear una nueva promesa sabe que se resolverá con otra, entonces no hay ninguna razón lógica para crear dicha promesa, solo reutilice la que planeó resolver. Tal error también fue acuñado como anti-patrón diferido