Programação Assíncrona em JavaScript: Guia Completo para Node.js

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução à programação assíncrona em JavaScript



JavaScript é uma linguagem de programação single-thread com modelo orientado a eventos não bloqueante. No ambiente Node.js, a programação assíncrona não é apenas uma opção conveniente, mas uma necessidade fundamental. Sem assincronicidade, uma aplicação servidora seria bloqueada a cada requisição ao banco de dados, leitura de arquivo ou chamada de rede, tornando-a inadequada para uso real.



Neste guia, vamos abordar os três principais paradigmas de programação assíncrona em JavaScript: Callback, Promise e async/await. Você aprenderá como o Event Loop funciona, como tratar erros e escrever código legível e performático para Node.js.



1. Callback: a base da assincronicidade



Callback (função de retorno) é uma função passada como argumento para outra função e executada após a conclusão de uma operação assíncrona. Este é o modelo mais antigo e básico de assincronicidade em JavaScript.



Exemplo simples com Callback



const fs = require('fs');

// Leitura assíncrona de arquivo com callbackfs.readFile('example.txt', 'utf8', (err, data) => { if (err) { console.error('Erro ao ler arquivo:', err); return; } console.log('Conteúdo do arquivo:', data);});

console.log('Leitura do arquivo iniciada...');// Saída: "Leitura do arquivo iniciada..." aparecerá antes do conteúdo do arquivo


Neste exemplo, a função callback será executada somente após o arquivo ser completamente lido. Enquanto isso, o fluxo principal continua sua execução — este é o comportamento não bloqueante.



Callback Hell (Inferno dos callbacks)



A principal desvantagem dos callbacks é a rápida perda de legibilidade com chamadas aninhadas:



// Inferno dos callbacksgetUser(1, (err, user) => {  if (err) throw err;  getPosts(user.id, (err, posts) => {    if (err) throw err;    getComments(posts[0].id, (err, comments) => {      if (err) throw err;      console.log(user.name, posts[0].title, comments);    });  });});


Esse código é difícil de depurar, manter e estender. Felizmente, o JavaScript moderno oferece soluções muito mais elegantes.



2. Promise: promessa de resultado



Promise (promessa) é um objeto que representa o resultado de uma operação assíncrona, que pode ser concluída (fulfilled), rejeitada (rejected) ou estar pendente (pending). Promises permitem evitar aninhamento e construir cadeias de chamadas.



Criação e uso de Promise



// Função que retorna uma Promisefunction readFilePromise(filename) {  return new Promise((resolve, reject) => {    const fs = require('fs');    fs.readFile(filename, 'utf8', (err, data) => {      if (err) {        reject(err); // Erro — promise rejeitada      } else {        resolve(data); // Sucesso — promise resolvida      }    });  });}

// Usando a promisereadFilePromise('example.txt') .then(data => { console.log('Conteúdo:', data); return data.length; }) .then(length => { console.log('Tamanho do texto:', length); }) .catch(err => { console.error('Erro:', err); });


Métodos Promise.all e Promise.race



Promise.all permite aguardar a conclusão de todas as promises, enquanto Promise.race aguarda a primeira a ser concluída:



const p1 = readFilePromise('file1.txt');const p2 = readFilePromise('file2.txt');const p3 = readFilePromise('file3.txt');

// Aguarda todos os três arquivosPromise.all([p1, p2, p3]) .then(([data1, data2, data3]) => { console.log('Todos os arquivos carregados'); console.log(data1, data2, data3); }) .catch(err => console.error('Erro em um dos arquivos:', err));

// Aguarda o primeiro a ser concluídoPromise.race([p1, p2, p3]) .then(firstResult => { console.log('Primeiro arquivo carregado:', firstResult); });


3. Async/Await: estilo síncrono para código assíncrono

Blogs

Book Recommendations