Introdução à Programação Assíncrona em TypeScript
O desenvolvimento web moderno é impensável sem programação assíncrona. Seja para requisições a APIs, trabalho com sistema de arquivos ou timers — todas essas operações exigem execução de código não bloqueante. TypeScript, como uma extensão do JavaScript, fornece ferramentas poderosas para trabalhar com assincronicidade, adicionando tipagem estrita e melhor legibilidade do código.
Neste guia, abordaremos detalhadamente todos os aspectos da programação assíncrona em TypeScript: desde Promise básicos até padrões avançados com async/await e execução paralela de tarefas.
1. Fundamentos de Promise em TypeScript
O que é Promise?
Promise (promessa) é um objeto que representa o resultado de uma operação assíncrona. Ele pode estar em um dos três estados:
- Pending (pendente) — estado inicial, a operação ainda não foi concluída.
- Fulfilled (resolvida) — a operação foi concluída com sucesso.
- Rejected (rejeitada) — a operação foi concluída com erro.
Criação de Promise com tipagem
TypeScript permite tipar estritamente os valores retornados por Promise. Vejamos um exemplo:
// Função que retorna uma Promise com tipo de dadofunction fetchUserData(userId: number): Promise<User> { return new Promise<User>((resolve, reject) => { setTimeout(() => { const user: User = { id: userId, name: 'Ivan Ivanov', email: 'ivan@example.com' }; if (userId > 0) { resolve(user); } else { reject(new Error('ID de usuário inválido')); } }, 1000); });}
// Interface para tipagem dos dadosinterface User { id: number; name: string; email: string;}
// Uso de PromisefetchUserData(1) .then((user: User) => { console.log(`Usuário: ${user.name}`); }) .catch((error: Error) => { console.error(`Erro: ${error.message}`); });Encadeamento de Promise (Chaining)
Promises podem ser encadeadas para execução sequencial de operações assíncronas:
function getUserPosts(userId: number): Promise<string[]> { return new Promise((resolve) => { setTimeout(() => resolve(['Post 1', 'Post 2', 'Post 3']), 500); });}
function getPostComments(postTitle: string): Promise<string[]> { return new Promise((resolve) => { setTimeout(() => resolve(['Comentário 1', 'Comentário 2']), 300); });}
// Encadeamento de PromisefetchUserData(1) .then((user) => { console.log(`Usuário encontrado: ${user.name}`); return getUserPosts(user.id); }) .then((posts) => { console.log(`Posts encontrados: ${posts.length}`); return getPostComments(posts[0]); }) .then((comments) => { console.log(`Comentários no primeiro post: ${comments.length}`); }) .catch((error) => { console.error('Ocorreu um erro:', error); });2. Async/Await — abordagem moderna
Sintaxe async/await
As palavras-chave async e await tornam o código assíncrono semelhante ao síncrono, melhorando significativamente sua legibilidade. Uma função marcada com async sempre retorna uma Promise.
// Função assíncrona com tipagem do valor de retornoasync function loadUserProfile(userId: number): Promise<UserProfile> { try { const user = await fetchUserData(userId); const posts = await getUserPosts(userId); return { user, posts, lastLogin: new Date() };