Promesas en JavaScript: estados, resolución y errores | Nicolás Garzón
Promise
JavaScript
Copiar const productPromise = loadProduct ( "product-1" ) ; Una promesa se encuentra en uno de estos estados:
Texto
Copiar pending
├─ fulfilled → value
└─ rejected → reasonUna vez settled —cumplida o rechazada— no cambia nuevamente.
JavaScript
Copiar const promise = new Promise ( ( resolve ) => {
resolve ( "first" ) ;
resolve ( "second" ) ;
} ) ;
promise. then ( console. log) ;
Una promesa puede resolverse adoptando el estado de otra promesa.
JavaScript
Copiar const inner = fetchData ( ) ;
const outer = new Promise ( ( resolve ) => {
resolve ( inner) ;
} ) ; outer quedó resuelta con inner, pero puede continuar pendiente hasta que inner termine.
Por eso resolved no siempre significa fulfilled inmediatamente .
JavaScript
Copiar console. log ( "A" ) ;
const promise = new Promise ( ( resolve ) => {
console. log ( "B" ) ;
resolve ( "done" ) ;
} ) ;
console. log ( "C" ) ; La función executor se ejecuta al construir la promesa. Las callbacks de then sí se programan como continuaciones posteriores.
JavaScript
Copiar function wait ( delay ) {
return new Promise ( ( resolve ) => {
setTimeout ( resolve, delay) ;
} ) ;
} El constructor debe utilizarse cuando adaptas una API basada en callbacks o controlas una operación que necesita exponer resolve y reject.
No envuelvas una promesa existente sin necesidad.
JavaScript
Copiar function load ( ) {
return new Promise ( ( resolve, reject ) => {
fetchData ( ) . then ( resolve, reject) ;
} ) ;
} JavaScript
Copiar function load ( ) {
return fetchData ( ) ;
} JavaScript
Copiar function readConfiguration ( storage ) {
return new Promise ( ( resolve, reject ) => {
const value = storage. getItem ( "config" ) ;
if ( value === null ) {
reject (
new Error ( "Configuration does not exist" ) ,
) ;
return ;
}
resolve ( value) ;
} ) ;
} Aunque JavaScript permite rechazar con cualquier valor, usar objetos Error conserva mejor contexto y traza.
JavaScript
Copiar promise. then (
( value ) => {
console. log ( "fulfilled" , value) ;
} ,
( reason ) => {
console. log ( "rejected" , reason) ;
} ,
) ; Normalmente se utiliza then para éxito y catch para rechazo, porque permite manejar errores del tramo anterior completo.
JavaScript
Copiar const nextPromise = promise. then ( ( value ) => {
return value * 2 ;
} ) ; nextPromise es distinta de promise.
La nueva promesa se comporta según el retorno de la callback:
Retorno Resultado de la nueva promesa Valor normal Fulfilled con ese valor Promise o thenable Adopta su resultado `throw` Rejected con ese error Sin retorno Fulfilled con `undefined`
JavaScript
Copiar loadUser ( )
. then ( ( user ) => {
return loadOrders ( user. id) ;
} )
. then ( ( orders ) => {
console. log ( orders) ;
} ) ; El segundo then espera la promesa retornada. No recibe una promesa anidada como valor ordinario.
JavaScript
Copiar loadUser ( )
. then ( ( user ) => {
loadOrders ( user. id) ;
} )
. then ( ( orders ) => {
console. log ( orders) ;
} ) ; La primera callback no retornó nada. La cadena perdió la operación interna.
JavaScript
Copiar loadProduct ( )
. then ( renderProduct)
. catch ( ( error ) => {
showError ( error) ;
} ) ; JavaScript
Copiar promise. then ( undefined , onRejected) ;
El rechazo original.
Un error lanzado por callbacks anteriores.
El rechazo de una promesa retornada.
JavaScript
Copiar loadPreferences ( )
. catch ( ( error ) => {
if ( error instanceof PreferencesNotFoundError ) {
return defaultPreferences;
}
throw error;
} )
. then ( applyPreferences) ; Retornar un valor desde catch convierte ese tramo en una promesa cumplida. Relanzar mantiene el fallo.
JavaScript
Copiar showLoading ( ) ;
loadProducts ( )
. then ( renderProducts)
. catch ( showError)
. finally ( hideLoading) ; finally no recibe el valor ni la razón porque su propósito normal es limpieza independiente del resultado.
Si termina normalmente, conserva el resultado anterior. Si lanza o retorna una promesa rechazada, reemplaza ese resultado.
JavaScript
Copiar Promise. resolve ( 10 ) ;
Promise. resolve ( existingPromise) ; Normaliza valores y thenables dentro de una promesa del constructor utilizado.
Un thenable es un objeto con un método then compatible.
JavaScript
Copiar const thenable = {
then ( resolve ) {
resolve ( "value" ) ;
} ,
} ;
Promise. resolve ( thenable)
. then ( console. log) ; La resolución de promesas adopta thenables, no únicamente instancias nativas de Promise.
JavaScript
Copiar const failed = Promise. reject (
new Error ( "Failed" ) ,
) ; La promesa ya está rechazada, pero sus manejadores continúan ejecutándose de forma asíncrona mediante jobs de promesas.
JavaScript
Copiar const {
promise,
resolve,
reject,
} = Promise. withResolvers ( ) ; Separa la creación de la promesa de sus funciones de resolución. Puede ser útil para adaptar eventos o construir primitivas de coordinación.
No debe utilizarse para exponer resolve indiscriminadamente por toda la aplicación; quien pueda resolver la promesa controla su contrato.
JavaScript
Copiar const request = fetch ( url) ; No existe request.cancel() en Promise. La operación subyacente debe aceptar una señal o mecanismo propio de cancelación.
JavaScript
Copiar Promise. reject (
new Error ( "Failed" ) ,
) ; Si ningún manejador asume el rechazo, el host puede reportarlo como unhandled rejection.
No significa necesariamente que el programa se detenga igual en todos los entornos, pero indica un fallo sin responsabilidad asignada.
JavaScript
Copiar function waitForMessage ( port ) {
const {
promise,
resolve,
reject,
} = Promise. withResolvers ( ) ;
function cleanup ( ) {
port. removeEventListener ( "message" , onMessage) ;
port. removeEventListener ( "messageerror" , onError) ;
}
function onMessage ( event ) {
cleanup ( ) ;
resolve ( event. data) ;
}
function onError ( event ) {
cleanup ( ) ;
reject (
new Error ( "Message could not be decoded" , {
cause : event,
} ) ,
) ;
}
port. addEventListener ( "message" , onMessage) ;
port. addEventListener ( "messageerror" , onError) ;
return promise;
} La promesa representa un solo resultado y los listeners se limpian al terminar.
Creer que el executor espera de forma asíncrona antes de ejecutarse.
Confundir resolved con fulfilled.
Olvidar retornar una promesa dentro de then.
Crear new Promise alrededor de otra promesa sin necesidad.
Rechazar con strings cuando necesitas contexto de error.
Pensar que una promesa cancela la operación subyacente.
Capturar un error y retornar undefined accidentalmente.
Exponer resolve y reject sin controlar quién puede usarlos.
Ignorar un rechazo porque “la UI sigue funcionando”.
Una Promise representa un resultado futuro único.
Puede estar pending, fulfilled o rejected.
El executor se ejecuta síncronamente.
Las reacciones de then y catch son posteriores.
Cada then, catch y finally produce otra promesa.
Retornar una promesa conecta ambas operaciones.
Lanzar dentro de una callback rechaza la siguiente promesa.
Las promesas no ofrecen cancelación automática.
¿Qué recibe el último then?
JavaScript
Copiar Promise. resolve ( 2 )
. then ( ( value ) => value * 3 )
. then ( ( value ) => {
Promise. resolve ( value + 1 ) ;
} )
. then ( console. log) ; Respuesta Recibe undefined. La segunda callback creó una promesa, pero no la retornó.
Encadenamiento y errores en promesas profundiza en composición, propagación, recuperación y promesas flotantes.