Desafio JavaScript
Promise.all vs Promise.allSettled
Enunciado
Crie uma função buscarUsuario(id) que retorna uma Promise que resolve após 500ms com um objeto { id, nome: 'Usuário ' + id } se id > 0, ou rejeita com new Error('ID inválido') se id <= 0. Use Promise.all() para buscar os IDs [1, 2, 3] e exiba os resultados. Depois, use Promise.allSettled() para buscar os IDs [4, -1, 5] e exiba o status e o valor/erro de cada um.
Requisitos
- A função
buscarUsuariodeve retornar uma Promise que resolve ou rejeita conforme a condição. - Use
Promise.all()com os IDs[1, 2, 3]e exiba os resultados no console. - Use
Promise.allSettled()com os IDs[4, -1, 5]e exiba o status e o valor/erro de cada resultado. - Trate erros do
Promise.all()com.catch().
Código inicial
function buscarUsuario(id) {
// Seu código aqui
}
// Promise.all
Promise.all([1, 2, 3].map(buscarUsuario))
.then(resultados => {
// exiba os resultados
})
.catch(erro => {
// exiba o erro
});
// Promise.allSettled
Promise.allSettled([4, -1, 5].map(buscarUsuario))
.then(resultados => {
// exiba o status e valor/erro de cada resultado
});
Saída esperada
Promise.all resultados: [ { id: 1, nome: 'Usuário 1' }, { id: 2, nome: 'Usuário 2' }, { id: 3, nome: 'Usuário 3' } ]
Promise.allSettled:
Status: fulfilled, Valor: { id: 4, nome: 'Usuário 4' }
Status: rejected, Erro: ID inválido
Status: fulfilled, Valor: { id: 5, nome: 'Usuário 5' }
Ver dica
Para Promise.allSettled, cada resultado tem uma propriedade status que pode ser 'fulfilled' ou 'rejected'. Se for 'fulfilled', o valor está em result.value; se for 'rejected', o erro está em result.reason.
Mostrar solução
function buscarUsuario(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) {
resolve({ id, nome: `Usuário ${id}` });
} else {
reject(new Error('ID inválido'));
}
}, 500);
});
}
// Promise.all: resolve todas ou rejeita na primeira falha
Promise.all([1, 2, 3].map(buscarUsuario))
.then(resultados => {
console.log('Promise.all resultados:', resultados);
})
.catch(erro => {
console.error('Promise.all erro:', erro.message);
});
// Promise.allSettled: sempre resolve com o status de cada promise
Promise.allSettled([4, -1, 5].map(buscarUsuario))
.then(resultados => {
console.log('Promise.allSettled:');
resultados.forEach(resultado => {
if (resultado.status === 'fulfilled') {
console.log(`Status: ${resultado.status}, Valor:`, resultado.value);
} else {
console.log(`Status: ${resultado.status}, Erro: ${resultado.reason.message}`);
}
});
});
Passo a passo
- A função
buscarUsuarioretorna uma Promise que, após 500ms, resolve com um objeto seid > 0ou rejeita com um erro seid <= 0. - Usamos
[1, 2, 3].map(buscarUsuario)para criar um array de Promises, uma para cada ID. Promise.all()recebe esse array e retorna uma nova Promise que resolve com um array de resultados quando todas forem resolvidas.- Encadeamos
.then()para exibir os resultados e.catch()para tratar qualquer rejeição. - Para
Promise.allSettled(), usamos[4, -1, 5].map(buscarUsuario)e passamos para o método. Promise.allSettled()sempre resolve com um array de objetos de resultado, independentemente de sucesso ou falha.- No
.then(), iteramos sobre os resultados e verificamosresultado.statuspara exibir o valor ou o erro.
Por que funciona
Promise.all() é útil quando você precisa que todas as Promises sejam bem-sucedidas para prosseguir; se qualquer uma falhar, a Promise resultante é rejeitada imediatamente. Já Promise.allSettled() é mais tolerante: ela espera que todas terminem e fornece um relatório completo, permitindo lidar com sucessos e falhas individualmente. Isso é crucial em cenários onde algumas operações podem falhar sem comprometer as demais.
Erros comuns
- Usar
Promise.all()quando algumas Promises podem falhar: isso fará com que todo o conjunto seja rejeitado, perdendo os resultados das que tiveram sucesso. UsePromise.allSettled()nesses casos. - Esquecer de tratar a rejeição do
Promise.all(): sem.catch(), um erro não tratado pode encerrar o processo. - Acessar
result.valuesem verificar o status: emPromise.allSettled(), se o status for'rejected',valueéundefinede o erro está emreason. - Não mapear corretamente os IDs para Promises: passar um array de números diretamente para
Promise.all()causa erro, pois não são Promises. Use.map().
Outra forma de resolver
Usar async/await com Promise.allSettled():
async function main() {
try {
const resultados = await Promise.all([1, 2, 3].map(buscarUsuario));
console.log('Promise.all resultados:', resultados);
} catch (erro) {
console.error('Promise.all erro:', erro.message);
}
const settled = await Promise.allSettled([4, -1, 5].map(buscarUsuario));
console.log('Promise.allSettled:');
settled.forEach(r => {
if (r.status === 'fulfilled') {
console.log(`Status: ${r.status}, Valor:`, r.value);
} else {
console.log(`Status: ${r.status}, Erro: ${r.reason.message}`);
}
});
}
main();
Essa forma é mais limpa, mas o enunciado pede o uso explícito de .then() e .catch().
Saída esperada
Promise.all resultados: [ { id: 1, nome: 'Usuário 1' }, { id: 2, nome: 'Usuário 2' }, { id: 3, nome: 'Usuário 3' } ]
Promise.allSettled:
Status: fulfilled, Valor: { id: 4, nome: 'Usuário 4' }
Status: rejected, Erro: ID inválido
Status: fulfilled, Valor: { id: 5, nome: 'Usuário 5' }