Desafio JavaScript
Execução paralela com Promise.all
Enunciado
Crie três funções assíncronas: buscarUsuario, buscarPosts e buscarComentarios, cada uma recebendo um id e retornando dados após um atraso específico (1000ms, 1500ms e 2000ms, respectivamente). Use Promise.all para buscar todos os dados em paralelo para o id 1 e imprimir o tempo total decorrido. Em seguida, faça o mesmo de forma sequencial (um após o outro) e compare os tempos. Trate possíveis erros com try/catch.
Requisitos
- As três funções devem ser
asynce usarawaitpara simular atrasos. - Use
Promise.allpara executar as três buscas em paralelo. - Meça e imprima o tempo total de cada abordagem (paralela e sequencial).
- Trate erros com
try/catchem ambos os casos.
Código inicial
// Crie as funções async buscarUsuario, buscarPosts, buscarComentarios
// Cada uma espera um tempo e retorna um objeto/array
// Use Promise.all para buscar em paralelo e meça o tempo
// Depois faça sequencialmente e compare
Saída esperada
Paralelo: usuário, posts, comentários em ~2000ms
Sequencial: usuário, posts, comentários em ~4500ms
Ver dica
Use Date.now() para medir o tempo. Para paralelo, crie as promises e passe para Promise.all. Para sequencial, use await uma após a outra.
Mostrar solução
// Função auxiliar para simular atraso
function esperar(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Busca usuário (1000ms)
async function buscarUsuario(id) {
await esperar(1000);
return { id, nome: 'Ana' };
}
// Busca posts (1500ms)
async function buscarPosts(id) {
await esperar(1500);
return ['Post 1', 'Post 2'];
}
// Busca comentários (2000ms)
async function buscarComentarios(id) {
await esperar(2000);
return ['Comentário 1', 'Comentário 2'];
}
// Execução paralela com Promise.all
async function executarParalelo(id) {
const inicio = Date.now();
try {
const [usuario, posts, comentarios] = await Promise.all([
buscarUsuario(id),
buscarPosts(id),
buscarComentarios(id),
]);
const tempo = Date.now() - inicio;
console.log(`Paralelo: ${usuario.nome}, ${posts.length} posts, ${comentarios.length} comentários em ~${tempo}ms`);
} catch (erro) {
console.error('Erro no paralelo:', erro.message);
}
}
// Execução sequencial
async function executarSequencial(id) {
const inicio = Date.now();
try {
const usuario = await buscarUsuario(id);
const posts = await buscarPosts(id);
const comentarios = await buscarComentarios(id);
const tempo = Date.now() - inicio;
console.log(`Sequencial: ${usuario.nome}, ${posts.length} posts, ${comentarios.length} comentários em ~${tempo}ms`);
} catch (erro) {
console.error('Erro no sequencial:', erro.message);
}
}
// Executa ambas as abordagens
async function main() {
await executarParalelo(1);
await executarSequencial(1);
}
main();
Passo a passo
- Definimos
esperarpara simular atrasos comsetTimeout. - Criamos as três funções
asyncque esperam tempos diferentes e retornam dados fictícios. - Em
executarParalelo, medimos o tempo inicial comDate.now(). - Criamos um array com as três chamadas de função (sem
awaitainda) e passamos paraPromise.all, que aguarda todas resolverem. - Desestruturamos os resultados e calculamos o tempo total, imprimindo a mensagem formatada.
- Em
executarSequencial, medimos o tempo e usamosawaituma chamada após a outra, somando os atrasos. - Imprimimos o resultado sequencial.
- Em
main, chamamos ambas as funções na ordem desejada.
Por que funciona
Promise.all recebe um array de promises e retorna uma única Promise que resolve quando todas as promises do array resolverem. Como as operações são independentes, elas podem rodar concorrentemente, reduzindo o tempo total para o maior atraso (2000ms). Já a execução sequencial soma os atrasos (1000+1500+2000 = 4500ms). O try/catch captura erros de qualquer uma das promises rejeitadas.
Erros comuns
- Usar
awaitantes de passar paraPromise.all: se fizerawait buscarUsuario(id)e depoisPromise.all([...]), a primeira já terá sido aguardada, perdendo o paralelismo. - Esquecer de tratar rejeições:
Promise.allrejeita imediatamente se qualquer promise falhar; semtry/catch, o erro não será tratado. - Medir o tempo incorretamente: usar
Date.now()antes e depois deawaité correto, mas se colocar dentro dotrypode incluir tempo de outras operações. - Confundir paralelismo com concorrência: JavaScript é single-thread, mas operações de I/O podem ser concorrentes;
Promise.allexplora isso.
Outra forma de resolver
Usar Promise.allSettled para aguardar todas as promises, mesmo que algumas falhem, e depois inspecionar os resultados. Útil quando você quer todos os resultados independentemente de erros.
Saída esperada
Paralelo: Ana, 2 posts, 2 comentários em ~2000ms
Sequencial: Ana, 2 posts, 2 comentários em ~4500ms