Programación asíncrona en TypeScript: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a la programación asíncrona en TypeScript

La programación asíncrona es un enfoque para escribir código donde las operaciones que requieren tiempo (como solicitudes al servidor, lectura de archivos, temporizadores) no bloquean la ejecución del hilo principal del programa. En el desarrollo web moderno, la asincronía no es solo una conveniencia, sino una necesidad. JavaScript y TypeScript, al ser lenguajes de un solo hilo, utilizan el bucle de eventos (Event Loop) para manejar operaciones asíncronas.

TypeScript añade a este potente paradigma el tipado estático, lo que hace que el código sea más predecible y seguro. En esta guía, analizaremos todos los aspectos de la programación asíncrona: desde los callbacks clásicos hasta los modernos async/await con tipado completo.



Fundamentos de la asincronía: de callbacks a promesas



El problema de los callbacks y el "infierno de los callbacks"

Inicialmente, la asincronía en JavaScript se implementaba mediante callbacks (funciones de retrollamada). Sin embargo, este enfoque rápidamente conducía a código ilegible:

function loadData(callback: (data: string) => void) {    setTimeout(() => {        callback("Datos cargados");    }, 1000);}

loadData((data) => { console.log(data); // Llamada anidada loadData((data2) => { console.log(data2); });});

Este código es difícil de depurar y mantener. TypeScript no resuelve el problema del anidamiento, pero ayuda a tipificar los parámetros de los callbacks.



Promesas (Promise) — el rescate del infierno

Una promesa es un objeto que puede estar en uno de tres estados: pending (pendiente), fulfilled (resuelta exitosamente) o rejected (rechazada con error). TypeScript permite tipificar estrictamente el tipo de datos que devolverá la promesa:

function fetchUser(id: number): Promise<User> {    return new Promise((resolve, reject) => {        setTimeout(() => {            if (id > 0) {                resolve({ id, name: "Iván Petrov" });            } else {                reject(new Error("ID incorrecto"));            }        }, 500);    });}

interface User { id: number; name: string;}

// UsofetchUser(1).then(user => { console.log(user.name); // TypeScript sabe que user es de tipo User}).catch(error => { console.error(error.message);});

Gracias al genérico Promise<User>, el compilador de TypeScript garantiza que dentro de .then() obtendremos un objeto de exactamente ese tipo.



Async/Await: asincronía elegante



Sintaxis y tipado

Las palabras clave async y await permiten escribir código asíncrono que parece síncrono. Una función marcada con async siempre devuelve una promesa:

async function getGreeting(name: string): Promise<string> {    return `¡Hola, ${name}!`;}

// El tipo del valor de retorno es Promise<string>const result: Promise<string> = getGreeting("Mundo");

Es importante recordar: si una función async devuelve algo que no es una promesa, TypeScript la envuelve automáticamente en una promesa.



Ejemplo con lógica real

Consideremos un escenario típico: obtener datos de una API y procesarlos:

interface Post {    userId: number;    id: number;    title: string;    body: string;}

async function fetchPosts(userId: number): Promise<Post[]> { const response = await fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userId}`); if (!response.ok) { throw new Error(`Error HTTP: ${response.status}`); } const data: Post[] = await response.json(); return data;}

async function displayPosts() { try { const posts = await fetchPosts(1); console.log(`Obtenidos ${posts.length} posts:`); posts.forEach(post => console.log(`- ${post.title}`));

Blogs

Book Recommendations