Imagine una función que devuelve una promesa (por ejemplo, buscar desde la API de búsqueda):
fetch(...) .then((response) => {...}) .catch((error) => {...}); ¿Cómo puedo saber si el error dentro de la instrucción catch se originó debido a un rechazo de promesa en lugar del código dentro de la declaración then ?
Algo como lo siguiente funcionará:
let success = false; fetch(...) .then((response) => {success = true; ...}) .catch((error) => {if(success) ...});Pero quiero saber si hay una forma mejor o más nativa de hacerlo. También he intentado hacer algo como:
fetch(...) .catch((promiseError) => {...}); .then((response) => {...}) .catch((thenError) => {...}); Pero creo que no funciona porque la response no se envía a la declaración de then (o al menos eso es lo que dice TS).
¿Cuál sería la mejor manera?
then acepta dos parámetros¹: una función para invocar el cumplimiento y otra para invocar el rechazo. Para que pueda manejar el rechazo inicial antes:
fetch(/*...*/) .then( // Fulfillment handler (response) => { /*...*/ }, // Rejection handler for `fetch` promise (error) => { /*...*/ } ) .catch((error) => { // This rejection handler only sees errors not handled above }); El primer controlador de rechazo (en la llamada then ) solo se llama para los rechazos de la promesa de fetch , no para los rechazos causados por errores en el controlador de cumplimiento.
El segundo controlador de rechazo (en la llamada catch ) se llama para los rechazos causados por errores (o promesas rechazadas) de los controladores anteriores (ya sea cumplimiento o rechazo); no se llama si se rechaza la promesa original (pero es posible que se llame si el primer controlador de rechazo arroja un error o devuelve una promesa que es/será rechazada).
Entonces, en aquellos casos en los que le importa, puede manejarlo más cerca de la fuente.
Tenga en cuenta que todos los controladores de rechazo que no arrojan un error ni devuelven una promesa que es/será rechazada convierten el rechazo (de la promesa original) en cumplimiento (de la de then / catch ). Eso puede ser importante para los controladores then .
Una cosa clave para entender esto es recordar que then (y sus envoltorios catch y finally ) devuelven una nueva promesa . Es por eso:
aPromise.then(onFulfilled).catch(onRejected);es diferente de
aPromise.then(onFulfilled, onRejected); El primero conecta un controlador de cumplimiento a aPromise , y luego conecta un controlador de rechazo a la promesa then regresa (lo que significa que se llamará al controlador de rechazo si aPromise rechaza o si el controlador de cumplimiento arroja un error o devuelve una promesa que rechaza) . Por el contrario, el segundo solo conecta controladores en aPromise , por lo que los errores/rechazos del controlador de cumplimiento no activan el controlador de rechazo.
¹ De hecho, .catch(fn) es solo un contenedor para .then(undefined, fn) . :-) enlace de especificaciones
si la función pass to devuelve then promesa,
promise .then( (async (response)=>{ ... }).catch((errorFromThen) => {}) ).catch((errorFromPromise) => {})o simplemente
promise .then( (response)=>{ try { ... } catch (errorFromThen) { ... } } ).catch((errorFromPromise) => {})