Programación asíncrona con TypeScript async/await
async/await es azúcar sintáctico para la programación asíncrona introducido en ES2017, lo que hace que el código asíncrono parezca código síncrono.
Diagrama SVG: flujo de ejecución de async/awaitLa figura anterior muestra las ventajas de async/await en comparación con Promise tradicional: código más conciso y un flujo de ejecución más claro.
Fundamentos de Promise
Promise representa el resultado final de una operación asíncrona.
Ejemplo
// Crear Promise
var promise = new Promise(function(resolve, reject) {
var success = true;
if (success) {
resolve("Operación exitosa");
} else {
reject("Operación fallida");
}
});
promise.then(function(result) {
console.log("Éxito: " + result);
})["catch"](function(error) {
console.log("Error: " + error);
});
var promise = new Promise(function(resolve, reject) {
var success = true;
if (success) {
resolve("Operación exitosa");
} else {
reject("Operación fallida");
}
});
promise.then(function(result) {
console.log("Éxito: " + result);
})["catch"](function(error) {
console.log("Error: " + error);
});
Resultado de ejecución:
Éxito: operación exitosa
Funciones async
Usa la palabra clave async para declarar funciones asíncronas.
Ejemplo
// La función async devuelve automáticamente una Promise
async function greet(): Promise<string> {
return "Hello, World!";
}
greet().then(function(result) {
console.log("Resultado: " + result);
});
// La función asíncrona devuelve una Promise
async function getData() {
return { name: "Alice", age: 25 };
}
getData().then(function(data) {
console.log("Datos: " + JSON.stringify(data));
});
async function greet(): Promise<string> {
return "Hello, World!";
}
greet().then(function(result) {
console.log("Resultado: " + result);
});
// La función asíncrona devuelve una Promise
async function getData() {
return { name: "Alice", age: 25 };
}
getData().then(function(data) {
console.log("Datos: " + JSON.stringify(data));
});
Resultado de ejecución:
结果: Hello, World!
数据: {"name":"Alice","age":25}
La palabra clave await
await espera a que la Promise se complete y obtiene el resultado.
Ejemplo
// Simular operación asíncrona
function delay(ms: number): Promise<string> {
return new Promise(function(resolve) {
setTimeout(function() {
resolve("¡Completado!");
}, ms);
});
}
async function main() {
console.log("Iniciando...");
var result = await delay(100);
console.log("Resultado: " + result);
console.log("Fin");
}
main();
function delay(ms: number): Promise<string> {
return new Promise(function(resolve) {
setTimeout(function() {
resolve("¡Completado!");
}, ms);
});
}
async function main() {
console.log("Iniciando...");
var result = await delay(100);
console.log("Resultado: " + result);
console.log("Fin");
}
main();
Resultado de ejecución:
Inicio... Resultado: ¡Completado! Fin
Manejo de errores
Usa try/catch para manejar errores asíncronos.
Ejemplo
function mayFail(shouldFail: boolean): Promise<string> {
return new Promise(function(resolve, reject) {
if (shouldFail) {
reject(new Error("Operación fallida"));
} else {
resolve("Operación exitosa");
}
});
}
async function handleError() {
try {
var result = await mayFail(true);
console.log("Resultado: " + result);
} catch (error) {
console.log("Error capturado: " + error.message);
}
}
handleError();
return new Promise(function(resolve, reject) {
if (shouldFail) {
reject(new Error("Operación fallida"));
} else {
resolve("Operación exitosa");
}
});
}
async function handleError() {
try {
var result = await mayFail(true);
console.log("Resultado: " + result);
} catch (error) {
console.log("Error capturado: " + error.message);
}
}
handleError();
Resultado de ejecución:
Error capturado: operación fallida
Ejecución en paralelo
Usa Promise.all para ejecutar múltiples operaciones asíncronas en paralelo.
Ejemplo
function fetchUser(id: number): Promise<{ id: number; name: string }> {
return Promise.resolve({ id: id, name: "User" + id });
}
async function main() {
// Ejecución en serie
console.time("Serie");
var user1 = await fetchUser(1);
var user2 = await fetchUser(2);
console.log("Serie completada: " + user1.name + ", " + user2.name);
console.timeEnd("Serie");
// Ejecución en paralelo
console.time("Paralelo");
var results = await Promise.all([fetchUser(1), fetchUser(2)]);
console.log("Paralelo completado: " + results[0].name + ", " + results[1].name);
console.timeEnd("Paralelo");
}
main();
return Promise.resolve({ id: id, name: "User" + id });
}
async function main() {
// Ejecución en serie
console.time("Serie");
var user1 = await fetchUser(1);
var user2 = await fetchUser(2);
console.log("Serie completada: " + user1.name + ", " + user2.name);
console.timeEnd("Serie");
// Ejecución en paralelo
console.time("Paralelo");
var results = await Promise.all([fetchUser(1), fetchUser(2)]);
console.log("Paralelo completado: " + results[0].name + ", " + results[1].name);
console.timeEnd("Paralelo");
}
main();
Resultado de ejecución:
串行完成: User1, User2 并行完成: User1, User2
Ventajas de async/await frente a Promise
- Código más conciso y legible
- Estilo de código síncrono
- Mejor stack de errores
- Fácil de depurar
Resumen
- async:Declarar funciones asíncronas
- await:Esperar una Promise
- Manejo de errores:try/catch
- Paralelo:Promise.all
Otras extensiones