JavaScript
Tutorial JavaScript: Promises
JavaScript promises: manejo de asincronía. Domina el manejo de asincronía en JavaScript utilizando promises con ejemplos detallados.
Aprende JavaScript y certifícateEstados y ciclo de vida: Pending, fulfilled y rejected en el flujo de una promesa
Las promesas en JavaScript representan operaciones asíncronas que pueden completarse en algún momento futuro. Cada promesa atraviesa diferentes estados durante su ciclo de vida, lo que permite gestionar de manera elegante el flujo de ejecución asíncrono.
Estados fundamentales de una promesa
Una promesa siempre se encuentra en uno de estos tres estados:
- Pending (pendiente): Estado inicial cuando se crea la promesa. La operación asíncrona aún no se ha completado ni ha fallado.
- Fulfilled (cumplida): La operación asíncrona se completó exitosamente.
- Rejected (rechazada): La operación asíncrona falló por algún motivo.
Las promesas que han sido resueltas (fulfilled) o rechazadas (rejected) se consideran settled (establecidas), lo que significa que han alcanzado un estado final y no pueden cambiar a otro estado.
Creación de una promesa
Para crear una promesa, utilizamos el constructor Promise
que recibe una función ejecutora con dos parámetros: resolve
y reject
:
const myPromise = new Promise((resolve, reject) => {
// Operación asíncrona
const success = true;
if (success) {
resolve('Operation completed successfully'); // Cambia a fulfilled
} else {
reject(new Error('Operation failed')); // Cambia a rejected
}
});
En este ejemplo, la promesa comienza en estado pending y, dependiendo del resultado de la operación, cambiará a fulfilled o rejected.
Visualización del ciclo de vida
Podemos observar los cambios de estado de una promesa mediante un ejemplo práctico:
console.log('Creating promise...');
const loadUserData = new Promise((resolve, reject) => {
console.log('Promise state: PENDING');
setTimeout(() => {
const randomSuccess = Math.random() > 0.3;
if (randomSuccess) {
console.log('Promise state: about to be FULFILLED');
resolve({ id: 1, name: 'John Doe' });
} else {
console.log('Promise state: about to be REJECTED');
reject(new Error('Failed to load user data'));
}
}, 2000);
});
// Observamos el estado actual
console.log('Promise created, waiting for settlement...');
Este código muestra cómo una promesa permanece en estado pending durante 2 segundos antes de resolverse o rechazarse.
Transiciones de estado
Es importante entender algunas reglas clave sobre las transiciones de estado:
- Una promesa solo puede cambiar de pending a fulfilled o de pending a rejected.
- Una vez que una promesa está en estado fulfilled o rejected, su valor o razón de rechazo no puede cambiar.
- Las transiciones de estado son irreversibles.
Inspección del estado actual
JavaScript no proporciona una forma directa de consultar el estado actual de una promesa, pero podemos crear una función auxiliar para demostrarlo:
function demonstratePromiseStates() {
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('Success!'), 2000);
});
// Al inicio
logPromiseState(promise, 'Initial');
// Después de 1 segundo (aún pending)
setTimeout(() => {
logPromiseState(promise, 'After 1 second');
}, 1000);
// Después de 3 segundos (ya fulfilled)
setTimeout(() => {
logPromiseState(promise, 'After 3 seconds');
}, 3000);
return promise;
}
function logPromiseState(promise, label) {
// Truco para detectar el estado
promise.then(
() => console.log(`${label}: FULFILLED`),
() => console.log(`${label}: REJECTED`)
);
console.log(`${label}: PENDING (if no message appears immediately)`);
}
demonstratePromiseStates();
Promesas en tiempo real
Veamos un ejemplo más práctico que simula una solicitud de red:
function fetchUserProfile(userId) {
console.log(`Fetching user ${userId}...`);
return new Promise((resolve, reject) => {
// Simulamos una solicitud de red
const startTime = Date.now();
setTimeout(() => {
const endTime = Date.now();
console.log(`Network request took ${endTime - startTime}ms`);
if (userId > 0) {
resolve({
id: userId,
name: 'Sample User',
email: `user${userId}@example.com`
});
} else {
reject(new Error('Invalid user ID'));
}
}, 1500);
});
}
// Uso
const userPromise = fetchUserProfile(42);
console.log('Promise created, application continues running...');
En este ejemplo, la promesa permanece en estado pending durante la simulación de la solicitud de red y luego cambia a fulfilled si el ID de usuario es válido o a rejected si no lo es.
Comportamiento de las promesas ya establecidas
Un aspecto interesante de las promesas es cómo se comportan cuando ya están establecidas (settled):
function createResolvedPromise() {
return Promise.resolve('Already fulfilled');
}
const resolvedPromise = createResolvedPromise();
// Incluso si agregamos handlers después, se ejecutarán inmediatamente
setTimeout(() => {
console.log('Adding handler to already fulfilled promise');
resolvedPromise.then(value => {
console.log(`Got value: ${value}`);
});
}, 2000);
Este comportamiento es crucial para entender cómo las promesas difieren de los simples callbacks, ya que capturan un resultado que persiste y puede ser consultado en cualquier momento futuro.
Propagación de estados
El estado de una promesa puede propagarse a través de cadenas de promesas, lo que es fundamental para el encadenamiento que veremos en secciones posteriores:
const initialPromise = new Promise((resolve, reject) => {
setTimeout(() => resolve(10), 1000);
});
// El estado fulfilled se propaga
const derivedPromise = initialPromise.then(value => {
console.log(`Initial promise fulfilled with: ${value}`);
return value * 2; // Esta promesa también se cumplirá
});
// derivedPromise estará en estado pending hasta que initialPromise se resuelva
Comprender el ciclo de vida y los estados de las promesas es esencial para dominar la programación asíncrona en JavaScript, ya que forma la base para técnicas más avanzadas como el encadenamiento y la composición de operaciones asíncronas.
Encadenamiento y composición: Métodos then, catch y finally para secuencias asíncronas
El verdadero poder de las promesas en JavaScript radica en su capacidad para encadenar operaciones asíncronas de forma legible y mantenible. Los métodos then()
, catch()
y finally()
nos permiten crear flujos de ejecución complejos sin caer en el temido "callback hell".
El método then()
El método then()
es la pieza fundamental del encadenamiento de promesas. Recibe hasta dos argumentos: una función de éxito y una función de error (opcional).
const fetchData = new Promise((resolve, reject) => {
setTimeout(() => resolve("Data received"), 1000);
});
fetchData.then(
data => console.log(data), // Función de éxito
error => console.error(error) // Función de error (opcional)
);
La característica más importante de then()
es que siempre devuelve una nueva promesa, lo que permite el encadenamiento:
function getUserData(userId) {
return fetch(`https://api.example.com/users/${userId}`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
});
}
getUserData(123)
.then(userData => {
console.log(`User name: ${userData.name}`);
return userData.id;
})
.then(userId => {
return fetch(`https://api.example.com/orders?userId=${userId}`);
})
.then(response => response.json())
.then(orders => {
console.log(`User has ${orders.length} orders`);
});
Transformación de valores
Cada then()
puede transformar el valor que recibe y pasarlo al siguiente en la cadena:
fetch('https://api.example.com/numbers')
.then(response => response.json())
.then(data => data.numbers) // Extrae solo el array de números
.then(numbers => numbers.filter(n => n % 2 === 0)) // Filtra números pares
.then(evenNumbers => evenNumbers.map(n => n * 2)) // Duplica cada número
.then(result => console.log(result)); // Muestra el resultado final
El método catch()
El método catch()
proporciona una forma elegante de manejar errores en cualquier punto de la cadena de promesas:
fetchUserData(userId)
.then(userData => processUserData(userData))
.then(processedData => saveToDatabase(processedData))
.catch(error => {
console.error('Error in the promise chain:', error);
return fallbackData(); // Proporciona datos alternativos
})
.then(finalData => {
// Este then se ejecutará con fallbackData si hubo un error
console.log('Final data:', finalData);
});
Un catch()
captura errores de todas las promesas anteriores en la cadena, lo que simplifica enormemente el manejo de errores. Es equivalente a usar then(null, errorHandler)
.
Propagación de errores
Los errores se propagan automáticamente a través de la cadena hasta encontrar un manejador de errores:
Promise.resolve(1)
.then(value => {
throw new Error('Something went wrong');
// Este error saltará al catch más cercano
})
.then(value => {
// Este then nunca se ejecuta debido al error anterior
console.log('This will not run');
})
.catch(error => {
console.error('Caught:', error.message);
return 'Recovery value';
})
.then(value => {
// Se ejecuta con el valor devuelto por catch
console.log('Recovered with:', value);
});
El método finally()
El método finally()
se ejecuta independientemente de si la promesa se cumple o se rechaza, lo que lo hace ideal para tareas de limpieza:
const loadingIndicator = document.getElementById('loading');
loadingIndicator.style.display = 'block';
fetchData()
.then(data => {
displayData(data);
})
.catch(error => {
showErrorMessage(error);
})
.finally(() => {
// Esto se ejecuta siempre, sin importar el resultado
loadingIndicator.style.display = 'none';
});
A diferencia de then()
y catch()
, el método finally()
no recibe ningún argumento y no puede modificar el valor que se está propagando a través de la cadena.
Patrones de encadenamiento avanzados
Ejecución secuencial
Cuando necesitamos ejecutar operaciones asíncronas en secuencia, donde cada una depende del resultado de la anterior:
function sequentialFetch(urls) {
let results = [];
return urls.reduce((promise, url) => {
return promise
.then(() => fetch(url))
.then(response => response.json())
.then(data => {
results.push(data);
return results; // Pasa los resultados acumulados
});
}, Promise.resolve());
}
sequentialFetch([
'https://api.example.com/resource1',
'https://api.example.com/resource2',
'https://api.example.com/resource3'
])
.then(allResults => console.log(allResults));
Bifurcación y reunificación
Podemos bifurcar un flujo de promesas y luego reunificarlo:
function getUserWithDetails(userId) {
return fetch(`/users/${userId}`)
.then(response => response.json())
.then(user => {
// Bifurcación: dos promesas independientes
const detailsPromise = fetch(`/users/${userId}/details`)
.then(response => response.json());
const ordersPromise = fetch(`/users/${userId}/orders`)
.then(response => response.json());
// Reunificación: espera a que ambas promesas se resuelvan
return Promise.all([user, detailsPromise, ordersPromise]);
})
.then(([user, details, orders]) => {
// Combina los resultados
return {
...user,
details,
orders
};
});
}
Manejo de errores específicos
Podemos implementar un manejo de errores más granular capturando y procesando errores específicos:
fetchData()
.then(data => processData(data))
.catch(error => {
if (error.name === 'NetworkError') {
console.log('Network error, retrying...');
return fetchData(); // Reintentar la operación
}
if (error.name === 'ValidationError') {
console.log('Data validation failed');
return getDefaultData(); // Usar datos predeterminados
}
// Para otros tipos de errores, propagar
throw error;
})
.then(finalData => {
// Procesar datos finales
})
.catch(error => {
// Manejador de último recurso
console.error('Unhandled error:', error);
});
Encadenamiento condicional
Podemos crear flujos condicionales dentro de cadenas de promesas:
authenticate()
.then(user => {
if (user.isAdmin) {
return fetchAdminData();
} else {
return fetchUserData(user.id);
}
})
.then(data => {
// Procesar los datos obtenidos
displayData(data);
});
El encadenamiento y composición de promesas nos permite escribir código asíncrono que fluye de manera natural, casi como si fuera síncrono, manteniendo la legibilidad y facilitando el manejo de errores en aplicaciones complejas.
Operaciones con múltiples promesas: Promise.all, Promise.race y Promise.allSettled
Cuando trabajamos con aplicaciones modernas, a menudo necesitamos gestionar múltiples operaciones asíncronas simultáneamente. JavaScript proporciona métodos estáticos en la clase Promise que nos permiten coordinar y componer varias promesas de manera eficiente.
Promise.all()
El método Promise.all()
toma un iterable de promesas (generalmente un array) y devuelve una nueva promesa que se resuelve cuando todas las promesas del iterable se han resuelto, o se rechaza si alguna de ellas falla.
const fetchUserData = fetch('/api/user').then(res => res.json());
const fetchUserPosts = fetch('/api/posts').then(res => res.json());
const fetchUserFollowers = fetch('/api/followers').then(res => res.json());
Promise.all([fetchUserData, fetchUserPosts, fetchUserFollowers])
.then(([userData, posts, followers]) => {
// Los tres resultados están disponibles aquí
console.log(`${userData.name} tiene ${posts.length} publicaciones y ${followers.length} seguidores`);
})
.catch(error => {
// Si cualquiera de las promesas falla, se ejecuta este catch
console.error('Error al cargar los datos:', error);
});
Características importantes de Promise.all()
:
- Orden preservado: Los resultados se devuelven en el mismo orden que las promesas originales, independientemente del orden en que se resuelvan.
- Fallo rápido: Si cualquier promesa es rechazada,
Promise.all()
se rechaza inmediatamente con ese error, sin esperar a que se completen las demás promesas. - Array vacío: Si se pasa un array vacío,
Promise.all()
se resuelve inmediatamente con un array vacío.
Caso de uso: Carga paralela de recursos
function loadPageResources() {
const resourceUrls = [
'/api/header-data',
'/api/main-content',
'/api/user-preferences',
'/api/sidebar-widgets'
];
const resourcePromises = resourceUrls.map(url =>
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`Failed to load ${url}: ${response.status}`);
}
return response.json();
})
);
return Promise.all(resourcePromises);
}
loadPageResources()
.then(resources => {
renderPage(resources);
})
.catch(error => {
showErrorPage(error);
});
Promise.race()
El método Promise.race()
también acepta un iterable de promesas, pero devuelve una promesa que se resuelve o rechaza tan pronto como una de las promesas del iterable se resuelve o rechaza, con el valor o razón de esa promesa.
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), 5000);
});
const dataPromise = fetch('/api/large-data').then(res => res.json());
Promise.race([dataPromise, timeoutPromise])
.then(data => {
console.log('Datos recibidos a tiempo:', data);
})
.catch(error => {
console.error('No se pudo completar la operación:', error);
});
Características importantes de Promise.race()
:
- Primera en completarse: Solo importa la primera promesa que se resuelva o rechace.
- Comportamiento de carrera: Como su nombre indica, las promesas "compiten" entre sí.
- Array vacío: Si se pasa un array vacío, la promesa resultante nunca se resolverá.
Caso de uso: Implementación de timeout
function fetchWithTimeout(url, timeout = 5000) {
const fetchPromise = fetch(url).then(res => res.json());
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`Request timed out after ${timeout}ms`));
}, timeout);
});
return Promise.race([fetchPromise, timeoutPromise]);
}
fetchWithTimeout('/api/data', 3000)
.then(data => {
displayData(data);
})
.catch(error => {
if (error.message.includes('timed out')) {
showTimeoutMessage();
} else {
showErrorMessage(error);
}
});
Promise.allSettled()
Introducido en ES2020, Promise.allSettled()
toma un iterable de promesas y devuelve una promesa que se resuelve cuando todas las promesas han sido establecidas (ya sea resueltas o rechazadas). A diferencia de Promise.all()
, nunca se rechaza.
const promises = [
fetch('/api/endpoint1').then(res => res.json()),
fetch('/api/endpoint2').then(res => res.json()),
fetch('/api/nonexistent').then(res => res.json())
];
Promise.allSettled(promises)
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promesa ${index} completada:`, result.value);
} else {
console.log(`Promesa ${index} fallida:`, result.reason);
}
});
});
Cada resultado en el array tiene esta estructura:
- Para promesas cumplidas:
{ status: 'fulfilled', value: resultado }
- Para promesas rechazadas:
{ status: 'rejected', reason: error }
Características importantes de Promise.allSettled()
:
- Siempre se resuelve: Nunca se rechaza, independientemente de si alguna promesa individual falla.
- Información completa: Proporciona el estado y resultado/razón de cada promesa.
- Orden preservado: Los resultados mantienen el mismo orden que las promesas originales.
Caso de uso: Operaciones parciales
function syncMultipleAccounts(accountIds) {
const syncPromises = accountIds.map(id =>
syncAccount(id)
.then(result => ({ status: 'fulfilled', id, result }))
.catch(error => ({ status: 'rejected', id, error }))
);
return Promise.allSettled(syncPromises)
.then(results => {
const successful = results.filter(r => r.status === 'fulfilled');
const failed = results.filter(r => r.status === 'rejected');
return {
totalAccounts: accountIds.length,
successfulSyncs: successful.length,
failedSyncs: failed.length,
failedAccountIds: failed.map(f => f.id)
};
});
}
syncMultipleAccounts([1001, 1002, 1003, 1004])
.then(summary => {
console.log(`Sincronización completada: ${summary.successfulSyncs}/${summary.totalAccounts} cuentas sincronizadas`);
if (summary.failedSyncs > 0) {
console.warn(`No se pudieron sincronizar ${summary.failedSyncs} cuentas:`, summary.failedAccountIds);
}
});
Promise.any()
Añadido en ES2021, Promise.any()
toma un iterable de promesas y devuelve una promesa que se resuelve tan pronto como una de las promesas del iterable se resuelve. Si todas las promesas son rechazadas, devuelve un AggregateError
que contiene todos los errores.
const mirrors = [
'https://mirror1.example.com/file',
'https://mirror2.example.com/file',
'https://mirror3.example.com/file'
];
const downloadPromises = mirrors.map(url => fetch(url));
Promise.any(downloadPromises)
.then(firstResponse => {
console.log('Descarga iniciada desde el primer mirror disponible');
return firstResponse.blob();
})
.then(blob => {
saveFile(blob);
})
.catch(error => {
// Se ejecuta solo si todos los mirrors fallan
console.error('Todos los mirrors fallaron:', error);
});
Características importantes de Promise.any()
:
- Primera en cumplirse: Devuelve la primera promesa que se resuelve correctamente.
- Ignora rechazos: Los rechazos se ignoran hasta que todas las promesas sean rechazadas.
- AggregateError: Si todas fallan, devuelve un error especial que contiene todos los errores individuales.
Caso de uso: Redundancia y failover
function fetchWithFailover(urls) {
const fetchPromises = urls.map(url =>
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return response.json();
})
);
return Promise.any(fetchPromises);
}
fetchWithFailover([
'https://api-primary.example.com/data',
'https://api-backup1.example.com/data',
'https://api-backup2.example.com/data'
])
.then(data => {
processData(data);
})
.catch(error => {
console.error('Todos los endpoints fallaron:', error);
showFallbackUI();
});
Comparación de métodos para múltiples promesas
Método | Resuelve cuando | Rechaza cuando | Caso de uso típico |
---|---|---|---|
Promise.all() |
Todas las promesas se resuelven | Cualquier promesa se rechaza | Operaciones interdependientes |
Promise.race() |
La primera promesa se resuelve | La primera promesa se rechaza | Timeouts, cancelaciones |
Promise.allSettled() |
Todas las promesas se establecen | Nunca se rechaza | Operaciones independientes |
Promise.any() |
Cualquier promesa se resuelve | Todas las promesas se rechazan | Redundancia, failover |
Estos métodos para trabajar con múltiples promesas nos permiten implementar patrones complejos de concurrencia y coordinación en aplicaciones JavaScript, manteniendo un código limpio y fácil de mantener.
Otros ejercicios de programación de JavaScript
Evalúa tus conocimientos de esta lección Promises con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Clases y objetos
Uso de operadores
Uso de operadores
Estructuras de control
Proyecto Manipulación DOM
Excepciones
Transformación con map()
Arrays y Métodos
Reto Métodos de Strings
Transformación con map()
Funciones flecha
Async / Await
Selección de elementos DOM
API Fetch
Encapsulación
Mapas con Map
Creación y uso de variables
Polimorfismo
Reto Funciones flecha
Tipos de datos
Reto Operadores avanzados
Promises
Reto Estructuras de control
Estructuras de control
Pruebas unitarias
Inmutabilidad y programación funcional pura
Funciones flecha
Polimorfismo
Reto Polimorfismo
Array
Transformación con map()
Reto Variables
Gestor de tareas con JavaScript
Proyecto Modificación de elementos DOM
Manipulación DOM
Funciones
Conjuntos con Set
Reto Prototipos y cadena de prototipos
Reto Encapsulación
Funciones flecha
Async / Await
Reto Excepciones
Reto Filtrado con filter() y find()
Creación y uso de variables
Excepciones
Promises
Funciones cierre (closure)
Reto Herencia
Herencia
Proyecto Eventos del DOM
Herencia
Selección de elementos DOM
Modificación de elementos DOM
Reto Clases y objetos
Filtrado con filter() y find()
Funciones cierre (closure)
Reto Destructuring de objetos y arrays
Callbacks
Funciones
Mapas con Map
Reducción con reduce()
Callbacks
Manipulación DOM
Introducción al DOM
Reto Funciones
Reto Funciones cierre (closure)
Promises
Reto Reducción con reduce()
Async / Await
Reto Estructuras de control
Eventos del DOM
Introducción a JavaScript
Async / Await
Promises
Selección de elementos DOM
Filtrado con filter() y find()
Callbacks
Creación de clases y objetos Restaurante
Reducción con reduce()
Filtrado con filter() y find()
Reducción con reduce()
Conjuntos con Set
Herencia de clases
Eventos del DOM
Clases y objetos
Modificación de elementos DOM
Mapas con Map
Proyecto carrito compra agoodshop
Introducción a JavaScript
Reto Mapas con Map
Funciones
Proyecto administrador de contactos
Reto Expresiones regulares
Tipos de datos
Clases y objetos
Array
Conjuntos con Set
Array
Encapsulación
Todas las lecciones de JavaScript
Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Javascript
Introducción Y Entorno
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Funciones Cierre (Closure)
Sintaxis
Métodos De Strings
Sintaxis
Funciones Cierre (Closure)
Sintaxis
Operadores Avanzados
Sintaxis
Funciones
Sintaxis
Expresiones Regulares
Sintaxis
Estructuras De Control
Sintaxis
Arrays Y Métodos
Estructuras De Datos
Conjuntos Con Set
Estructuras De Datos
Mapas Con Map
Estructuras De Datos
Conjuntos Con Set
Estructuras De Datos
Funciones Flecha
Programación Funcional
Filtrado Con Filter() Y Find()
Programación Funcional
Transformación Con Map()
Programación Funcional
Reducción Con Reduce()
Programación Funcional
Funciones Flecha
Programación Funcional
Transformación Con Map()
Programación Funcional
Inmutabilidad Y Programación Funcional Pura
Programación Funcional
Clases Y Objetos
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
This Y Contexto
Programación Orientada A Objetos
Patrón De Módulos Y Namespace
Programación Orientada A Objetos
Prototipos Y Cadena De Prototipos
Programación Orientada A Objetos
Destructuring De Objetos Y Arrays
Programación Orientada A Objetos
Manipulación Dom
Dom
Selección De Elementos Dom
Dom
Modificación De Elementos Dom
Dom
Eventos Del Dom
Dom
Localstorage Y Sessionstorage
Dom
Bom (Browser Object Model)
Dom
Callbacks
Programación Asíncrona
Promises
Programación Asíncrona
Async / Await
Programación Asíncrona
Promises
Programación Asíncrona
Api Fetch
Programación Asíncrona
Async / Await
Programación Asíncrona
Naturaleza De Js Y Event Loop
Programación Asíncrona
Callbacks
Programación Asíncrona
Websockets
Programación Asíncrona
Módulos En Es6
Construcción
Configuración De Bundlers Como Vite
Construcción
Eslint Y Calidad De Código
Construcción
Npm Y Dependencias
Construcción
Introducción A Pruebas En Js
Testing
Pruebas Unitarias
Testing
En esta lección
Objetivos de aprendizaje de esta lección
- Entender el concepto de promesas en JavaScript y su utilidad para operaciones asincrónicas.
- Aprender a crear promesas utilizando el constructor
Promise
. - Conocer los métodos
then
,catch
yfinally
para consumir y manejar el resultado de las promesas. - Familiarizarse con el encadenamiento de promesas para realizar operaciones asincrónicas en secuencia.
- Aprender a manejar múltiples promesas en paralelo utilizando
Promise.all
. - Entender cómo las promesas mejoran la legibilidad y estructura del código en situaciones con operaciones asíncronas.