Las promesas representan un valor que puede estar disponible ahora, en el futuro o nunca.
const miPromesa = new Promise((resolve, reject) => {
const exito = true; // Simulamos condición
if (exito) {
resolve('Operación exitosa!');
} else {
reject('Algo salió mal');
}
});
miPromesa
.then((resultado) => {
console.log(resultado); // 'Operación exitosa!'
})
.catch((error) => {
console.error(error); // 'Algo salió mal'
})
.finally(() => {
console.log('La promesa finalizó');
});
.then()
Async/Await es una forma más moderna y legible de trabajar con código asíncrono.
async function obtenerDatos() {
try {
const respuesta = await fetch('https://api.example.com/data');
const datos = await respuesta.json();
console.log(datos);
return datos;
} catch (error) {
console.error('Error al obtener datos:', error);
throw error;
}
}
// Dentro de una función async
async function procesarDatos() {
try {
const datos = await obtenerDatos();
console.log('Datos procesados:', datos);
} catch (error) {
console.error('Error en procesamiento:', error);
}
}
// Llamada a la función
procesarDatos();
await
solo puede usarse dentro de funciones marcadas con async
.
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error al obtener datos:', error);
throw error;
}
}
// Uso
fetchData('https://api.example.com/posts')
.then(data => console.log(data))
.catch(error => console.error(error));
class ApiClient {
constructor(baseURL) {
this.baseURL = baseURL;
this.token = null;
}
async request(endpoint, options = {}) {
const url = `${this.baseURL}${endpoint}`;
const headers = {
'Content-Type': 'application/json',
...options.headers
};
if (this.token) {
headers['Authorization'] = `Bearer ${this.token}`;
}
const config = {
...options,
headers
};
try {
const response = await fetch(url, config);
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Error en la solicitud');
}
return await response.json();
} catch (error) {
console.error('Error en la solicitud:', error);
throw error;
}
}
// Métodos específicos
async get(endpoint) {
return this.request(endpoint);
}
async post(endpoint, body) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(body)
});
}
// ...otros métodos (put, delete, etc)
}
// Uso
const api = new ApiClient('https://api.example.com');
api.get('/posts').then(data => console.log(data));
class AuthService {
constructor() {
this.token = localStorage.getItem('jwt') || null;
}
async login(credentials) {
try {
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(credentials)
});
if (!response.ok) {
throw new Error('Credenciales inválidas');
}
const data = await response.json();
this.setToken(data.token);
return data;
} catch (error) {
console.error('Error en login:', error);
throw error;
}
}
setToken(token) {
this.token = token;
localStorage.setItem('jwt', token);
}
logout() {
this.token = null;
localStorage.removeItem('jwt');
}
isAuthenticated() {
return !!this.token;
}
// Verificar si el token está expirado
isTokenExpired() {
if (!this.token) return true;
try {
const payload = JSON.parse(atob(this.token.split('.')[1]));
return payload.exp * 1000 < Date.now();
} catch (error) {
console.error('Error al decodificar token:', error);
return true;
}
}
}
class ApiClientWithAuth extends ApiClient {
constructor(baseURL, authService) {
super(baseURL);
this.authService = authService;
}
async request(endpoint, options = {}) {
// Verificar si el token está expirado
if (this.authService.isTokenExpired()) {
try {
// Lógica para refrescar el token
const newToken = await this.refreshToken();
this.authService.setToken(newToken);
} catch (error) {
this.authService.logout();
throw new Error('Sesión expirada, por favor inicie sesión nuevamente');
}
}
return super.request(endpoint, options);
}
async refreshToken() {
const response = await fetch('https://api.example.com/auth/refresh', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.authService.token}`
}
});
if (!response.ok) {
throw new Error('No se pudo refrescar el token');
}
const data = await response.json();
return data.token;
}
}
// auth.js
class AuthService {
// ...implementación anterior
}
// api.js
class ApiClient {
// ...implementación anterior
}
class ApiClientWithAuth extends ApiClient {
// ...implementación anterior
}
// Instancias globales
const authService = new AuthService();
const api = new ApiClientWithAuth('https://api.example.com', authService);
// Login
async function handleLogin(email, password) {
try {
const userData = await authService.login({ email, password });
console.log('Login exitoso:', userData);
return userData;
} catch (error) {
console.error('Error en login:', error);
throw error;
}
}
// Obtener datos protegidos
async function getProtectedData() {
if (!authService.isAuthenticated()) {
throw new Error('No autenticado');
}
try {
const data = await api.get('/protected-route');
console.log('Datos protegidos:', data);
return data;
} catch (error) {
console.error('Error al obtener datos protegidos:', error);
throw error;
}
}
// Logout
function handleLogout() {
authService.logout();
console.log('Sesión cerrada');
}
try/catch
o .catch()
await
al llamar funciones asyncPromise.all()
para múltiples solicitudes paralelas