Me cuesta entender 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 número es <0
prueba2 falla si número es > 10
y prueba3 falla si número no lo es 100
. En este caso, test2 solo falla.
Intenté ejecutar y hacer que test2Async fallara, tanto ANTES como DESPUÉS se comporta de la misma manera y eso no está ejecutando el test3Async. ¿Alguien puede explicarme la principal diferencia entre colocar capturas 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 una promesa? . Me imagino que es un problema diferente y vale la pena publicar otro tema.
fuente
Respuestas:
Entonces, básicamente estás preguntando cuál es la diferencia entre estos dos (dónde
p
está una promesa creada a partir de un código anterior):y
Existen diferencias cuando p resuelve o rechaza, pero si esas diferencias importan o no depende de lo que haga el código dentro de los controladores
.then()
o.catch()
.Qué sucede cuando
p
resuelve:En el primer esquema, cuando se
p
resuelve,.then()
se llama al controlador. Si ese.then()
controlador devuelve un valor u otra promesa que finalmente se resuelve,.catch()
se omite el controlador. Pero, si el.then()
manejador arroja o devuelve una promesa que finalmente se rechaza, entonces el.catch()
manejador ejecutará tanto un rechazo en la promesa originalp
como un error que ocurra en el.then()
manejador.En el segundo esquema, cuando se
p
resuelve,.then()
se llama al controlador. Si ese.then()
manejador lanza o devuelve una promesa que eventualmente rechaza, entonces el.catch()
manejador no puede captar eso porque está antes que él en la cadena.Entonces, esa es la diferencia n. ° 1. Si el
.catch()
controlador es DESPUÉS, también puede detectar errores dentro del.then()
controlador.Que pasa cuando
p
rechaza:Ahora, en el primer esquema, si la promesa se
p
rechaza,.then()
se omite el.catch()
controlador y se llamará al controlador como era de esperar. Lo que haces en el.catch()
controlador determina qué se devuelve como resultado final. Si solo devuelve un valor del.catch()
controlador 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.catch()
controlador, la promesa devuelta permanece rechazada.En el segundo esquema, si la promesa se
p
rechaza,.catch()
se llama al controlador. Si devuelve un valor normal o una promesa que finalmente se resuelve desde el.catch()
controlador (por lo tanto, "maneja" el error), entonces la cadena de promesa cambia al estado resuelto y se llamará al.then()
controlador posterior.catch()
.Entonces esa es la diferencia # 2. Si el
.catch()
controlador es ANTES, entonces puede manejar el error y permitir.then()
que se siga llamando al controlador.Cuándo usar cuál:
Utilice el primer esquema si solo desea un
.catch()
controlador que pueda detectar errores en la promesa originalp
o en el.then()
controlador y un rechazo dep
debería omitir el.then()
controlador.Utilice el segundo esquema si desea poder detectar errores en la promesa original
p
y tal vez (dependiendo de las condiciones), permitir que la cadena de promesa continúe como se resolvió, ejecutando así el.then()
controlador.La otra opcion
Hay otra opción para usar ambas devoluciones de llamada a las que puede pasar
.then()
como en:Esto garantiza que solo uno de
fn1
ofn2
será llamado. Si sep
resuelve, entoncesfn1
se llamará. Sip
rechaza, entoncesfn2
será llamado. Ningún cambio de resultado enfn1
nunca puede hacer quefn2
te llamen o viceversa. Por lo tanto, si desea estar absolutamente seguro de que solo se llama a uno de sus dos controladores, independientemente de lo que suceda en los mismos controladores, puede usarp.then(fn1, fn2)
.fuente
.then()
y.catch()
, que respondes. Además, da algunos consejos sobre cuándo usar qué orden, donde creo que es apropiado mencionar una tercera opción, es decir, pasar el controlador de éxito y error a .then () . En ese caso, se llamará a un controlador como máximo.Promise.reject(new Error("F")).then(x => x).catch(e => {console.log(e); return [1]}).then(console.log)
yPromise.resolve([2]).then(x => x).catch(e => [1]).then(console.log)
.then(this.setState({isModalOpen: false}))
. No está pasando una referencia de función a.then()
para que el código en los parens se ejecute inmediatamente (antes de que se resuelva la promesa). Debería serlo.then(() => this.setState({isModalOpen: false}))
.La respuesta de jfriend00 es excelente, pero pensé que sería una buena idea agregar el código sincrónico análogo.
es similar al sincrónico:
Si
iMightThrow()
no lanza,then()
se llamará. Si lanza (o sithen()
lanza él mismo), entonceshandleCatch()
será llamado. Observe cómo elcatch
bloque no tiene control sobre sithen
se llama o no .Por otra parte,
es similar al sincrónico:
En este caso, si
iMightThrow()
no lanza,then()
se ejecutará. Si arroja, entonces dependerá dehandleCatch()
decidir sithen()
se llama, porque si sehandleCatch()
vuelve a lanzar,then()
no se llamará, ya que la excepción se lanzará al llamador inmediatamente. SihandleCatch()
puede manejar el problema con elegancia, entoncesthen()
será llamado.fuente
then()
en unfinally{...}
then()
enfinally{...}
, ¿no forma incorrecta puede llamar incluso sihandleCatch()
lanza? Tenga en cuenta que mi objetivo era mostrar código síncrono análoga, no es sugerir diferentes formas de manejo de excepciones