Programação Assíncrona em TypeScript: Guia Completo para Iniciantes
O desenvolvimento web moderno é impossível sem entender programação assíncrona. TypeScript, como uma extensão do JavaScript, fornece ferramentas poderosas para trabalhar com código assíncrono, tornando-o mais seguro e previsível. Neste guia, vamos abordar os conceitos-chave da programação assíncrona em TypeScript, começando pelos fundamentos e terminando com exemplos práticos.
O que é programação assíncrona e por que ela é necessária?
Na programação síncrona, o código é executado estritamente de forma sequencial: cada operação seguinte espera a conclusão da anterior. Isso cria problemas ao trabalhar com tarefas demoradas, como requisições ao servidor, leitura de arquivos ou timers. A programação assíncrona permite executar essas tarefas em segundo plano, sem bloquear o fluxo principal de execução.
TypeScript adiciona tipagem estrita ao JavaScript assíncrono, o que ajuda a detectar erros em tempo de compilação. Por exemplo, Promises tipadas permitem saber exatamente qual tipo de dado uma função assíncrona retornará.
// Código síncrono - bloqueia a execuçãofunction fetchData(): string { // Operação demorada return "dados";}
// Código assíncrono - não bloqueiaasync function fetchDataAsync(): Promise<string> { const response = await fetch('/api/data'); return response.json();}Fundamentos: Callback, Promise e Async/Await
Historicamente, a assincronicidade em JavaScript começou com funções callback, que eram passadas como argumentos. No entanto, essa abordagem levava ao "callback hell" — estruturas profundamente aninhadas, difíceis de entender e depurar.
Promises resolveram esse problema fornecendo uma sintaxe encadeada. Uma Promise é um objeto que representa o resultado de uma operação assíncrona, podendo estar em um de três estados: pending (pendente), fulfilled (concluída) ou rejected (rejeitada).
// Exemplo de Promise em TypeScriptfunction loadUser(id: number): Promise<User> { return new Promise((resolve, reject) => { setTimeout(() => { if (id > 0) { resolve({ id, name: "Alice" }); } else { reject(new Error("ID de usuário inválido")); } }, 1000); });}
// UsoloadUser(1) .then(user => console.log(user)) .catch(error => console.error(error));Async/Await é um açúcar sintático sobre Promises, que torna o código assíncrono semelhante ao síncrono. A palavra-chave async antes de uma função indica que ela retorna uma Promise, e await pausa a execução até obter o resultado.
// Async/Await em TypeScriptasync function getUserData(): Promise<void> { try { const user = await loadUser(1); console.log(user.name); // "Alice" } catch (error) { console.error("Erro ao carregar:", error); }}
getUserData();Tipagem de funções assíncronas em TypeScript
Uma das principais vantagens do TypeScript é a tipagem estrita. Para funções assíncronas, é importante especificar corretamente o tipo da Promise retornada. Se uma função retorna uma string, o tipo será Promise<string>. O compilador TypeScript verificará se você não está tentando usar o resultado antes de obtê-lo.
Vamos considerar um exemplo com uma requisição de API tipada:
interface Todo { userId: number; id: number; title: string; completed: boolean;}
async function fetchTodo(id: number): Promise<Todo> { const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`); if (!response.ok) { throw new Error(`Erro HTTP! status: ${response.status}`); } return await response.json() as Todo;}
// Uso com tipagemasync function displayTodo(): Promise<void> { const todo = await fetchTodo
```