style body attribute javascript node.js promise bluebird

javascript - body - title css



Colocación de la captura ANTES y DESPUÉS (2)

Tengo problemas para comprender la diferencia entre poner .catch ANTES y DESPUÉS en una promesa anidada.

Alternativa 1:

test1Async(10).then((res) => { return test2Async(22) .then((res) => { return test3Async(100); }).catch((err) => { throw "ERROR AFTER THEN"; }); }).then((res) => { console.log(res); }).catch((err) => { console.log(err); });

Alternativa 2:

test1Async(10).then((res) => { return test2Async(22) .catch((err) => { throw "ERROR BEFORE THEN"; }) .then((res) => { return test3Async(100); }); }).then((res) => { console.log(res); }).catch((err) => { console.log(err); });

El comportamiento de cada función es el siguiente: prueba1 falla si el número es <0 prueba2 falla si el número es > 10 y prueba3 falla si el número no es 100 . En este caso, test2 solo falla.

Traté de ejecutar y hacer que test2Async falle, ANTES y DESPUÉS se comporta de la misma manera y eso no está ejecutando test3Async. ¿Alguien puede explicarme la diferencia principal para colocar la captura en diferentes lugares?

En cada función, console.log(''Running test X'') para verificar si se ejecuta.

Esta pregunta surge debido al hilo anterior que publiqué ¿Cómo convertir la devolución de llamada anidada en promesa? . Me imagino que es un problema diferente y vale la pena publicar otro tema.


Entonces, básicamente, se pregunta cuál es la diferencia entre estos dos (donde p es una promesa creada a partir de algún código anterior):

return p.then(...).catch(...);

y

return p.catch(...).then(...);

Existen diferencias cuando p resuelve o rechaza, pero si esas diferencias importan o no depende de lo que .then() el código dentro de los .then() o .catch() .

Qué sucede cuando p resuelve:

En el primer esquema, cuando p resuelve, se llama al controlador .then() . Si ese controlador .then() devuelve un valor u otra promesa que finalmente se resuelve, entonces se omite el controlador .catch() . Pero, si el controlador .then() arroja o devuelve una promesa que eventualmente rechaza, entonces el controlador .catch() se ejecutará tanto para un rechazo en la promesa original p , como para un error que ocurre en el .then() entrenador de animales.

En el segundo esquema, cuando p resuelve, se llama al controlador .then() . Si ese manejador .then() arroja o devuelve una promesa que eventualmente rechaza, entonces el manejador .catch() no puede atrapar eso porque está antes en la cadena.

Entonces, esa es la diferencia # 1. Si el controlador .catch() está DESPUÉS, también puede detectar errores dentro del controlador .then() .

Qué sucede cuando p rechaza:

Ahora, en el primer esquema, si la promesa p rechaza, entonces se omite el controlador .catch() y se llamará al controlador .catch() como era de esperar. Lo que haces en el controlador .catch() determina lo que se devuelve como resultado final. Si solo devuelve un valor del controlador .catch() o devuelve una promesa que finalmente se resuelve, entonces la cadena de promesa cambia al estado resuelto porque "manejó" el error y regresó normalmente. Si arroja o devuelve una promesa rechazada en el controlador .catch() , la promesa devuelta permanece rechazada.

En el segundo esquema, si la promesa p rechaza, se llama al controlador .catch() . Si devuelve un valor normal o una promesa que finalmente se resuelve desde el controlador .catch() ("manejando" el error), la cadena de promesa cambia al estado resuelto y al controlador .then() después del .catch() sera llamado.

Entonces esa es la diferencia # 2. Si el controlador .catch() está ANTES, entonces puede manejar el error y permitir que se .then() al controlador .then() .

Cuándo usar qué:

Utilice el primer esquema si solo desea un controlador .catch() que pueda detectar errores en la promesa original p o en el controlador .then() y un rechazo de p debería omitir el controlador .then() .

Use el segundo esquema si desea poder detectar errores en la promesa original p y tal vez (según las condiciones), permita que la cadena de la promesa continúe tal como se resolvió, ejecutando así el controlador .then() .

La otra opcion

Hay otra opción para usar ambas devoluciones de llamada que puede pasar a .then() como en:

p.then(fn1, fn2)

Esto garantiza que solo se fn1 uno de fn1 o fn1 . Si p resuelve, se fn1 a fn1 . Si p rechaza, se llamará a fn2 . Ningún cambio de resultado en fn1 puede hacer que se fn1 a fn1 o viceversa. Por lo tanto, si desea asegurarse absolutamente de que solo se llama a uno de sus dos controladores, independientemente de lo que ocurra en los mismos controladores, puede usar p.then(fn1, fn2) .


La respuesta de jfriend00 es excelente, pero pensé que sería una buena idea agregar el código síncrono análogo.

return p.then(...).catch(...);

es similar a la síncrona:

try { iMightThrow() // like `p` then() } catch (err) { handleCatch() }

Si iMightThrow() no se lanza, then() llamará a then() . Si lanza (o si then() lanza), se handleCatch() . Observe cómo el bloque catch no tiene control sobre si se llama o no.

Por otra parte,

return p.catch(...).then(...);

es similar a la síncrona:

try { iMightThrow() } catch (err) { handleCatch() } then()

En este caso, si iMightThrow() no se lanza, then() se ejecutará. Si se lanza, entonces handleCatch() de handleCatch() decidir si se llama a then() , porque si se handleCatch() , entonces no se llamará a then() , ya que la excepción se lanzará a la persona que llama de inmediato. Si handleCatch() puede manejar el problema con gracia, se handleCatch() .