Funções Promise.all, Promise.allSettled, Promise.any e Promise.race em JavaScript
As funções Promise.all
, Promise.allSettled
, Promise.any
e Promise.race
permitem agrupar a execução de várias promises.
Função Promise.all
A função Promise.all
recebe um array de promises e retorna uma nova promise que é resolvida quando todas as promises do array forem resolvidas ou rejeitada quando uma das promises for rejeitada.
Vamos analisar o seguinte código:
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "World");
});
promise1.then((value) => console.log(value)); // Hello
promise2.then((value) => console.log(value)); // World
Aqui, definimos duas promises. A operação assíncrona da primeira promise é executada após 1000 milissegundos, enquanto a ação da segunda promise é executada após 500 milissegundos. Ambas as promises são executadas independentemente uma da outra. A saída no console é:
Hello World
A função Promise.all()
permite combinar várias promises e executá-las em paralelo como uma única unidade. Como parâmetro, a função aceita um conjunto de promises:
Promise.all([promise1, promise2, ...promiseN]);
O resultado retornado pela função é um novo objeto Promise
.
Agora, vamos alterar o exemplo anterior usando a função Promise.all()
:
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "World");
});
Promise.all([promise1, promise2]).then((values) => {
const [promise1data, promise2data] = values;
console.log(promise1data, promise2data); // Hello World
});
Agora, os dados de ambas as promises são retornados juntos e estão disponíveis no método then()
como um array de values. A saída no console será:
Hello World
Os valores de todas as promises são retornados somente se todas forem concluídas com sucesso. No entanto, se uma operação assíncrona de pelo menos uma promise falhar devido à lógica interna ou ao chamar a função reject()
, todas as promises entrarão no estado de rejeição (rejected
), como mostrado a seguir:
const promise1 = new Promise((resolve, reject) => {
reject("Erro inesperado");
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "World");
});
Promise.all([promise1, promise2])
.then((values) => {
const [promise1data, promise2data] = values;
console.log(promise1data, promise2data);
})
.catch((error) => console.log(error)); // Erro inesperado
Neste caso, explicitamente colocamos a primeira promise no estado de rejeição (rejected
), e, consequentemente, todas as promises passadas para a função Promise.all()
também entram neste estado. Em seguida, através do método catch()
, podemos tratar o erro ocorrido.
Promise.allSettled
Outra função é a Promise.allSettled()
, que assim como Promise.all()
, aceita um conjunto de promises e as executa como uma unidade, mas retorna um objeto com o status e o resultado da promise:
const promise1 = new Promise((resolve, reject) => {
reject("Erro inesperado");
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, "World");
});
Promise.allSettled([promise1, promise2]).then((values) => {
const [promise1data, promise2data] = values;
console.log(promise1data); // {status: "rejected", reason: "Erro inesperado"}
console.log(promise2data); // {status: "fulfilled", value: "World"}
});
Quando ocorre um erro em uma das promises (como no exemplo acima com a primeira promise), a função ainda passa os resultados para o método then()
, que segue na cadeia. Cada resultado representa um objeto. A primeira propriedade deste objeto, status, descreve o status
ou estado da promise. Se ocorreu um erro, o status será rejected
, e a segunda propriedade representará o objeto de erro. Se a promise foi concluída com sucesso, o status será fulfilled
, e a segunda propriedade, value
, armazenará o resultado da promise.
Promise.race
A função Promise.race()
também aceita várias promises, mas retorna a primeira promise que for concluída (independentemente de ter sido concluída com sucesso ou erro):
const promise1 = new Promise((resolve) => {
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve) => {
setTimeout(resolve, 1000, "World");
});
Promise.race([promise1, promise2])
.then((value) => console.log(value)) // Hello
.catch((error) => console.log(error));
Neste caso, a primeira promise concluída será a promise1
. Portanto, no método then(value => console.log(value))
, o valor será a string "Hello".
Promise.any
A função Promise.any()
aceita várias promises e retorna a primeira promise que foi concluída com sucesso:
const promise1 = new Promise((resolve, reject) => {
reject("erro na promise1");
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve) => {
setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
.then((value) => console.log(value)) // World
.catch((error) => console.log(error));
Neste caso, a primeira promise concluída será a promise1
, porém, ela termina com um erro. Portanto, no método then(value => console.log(value))
, o valor será a string "World", que é o resultado da promise2
, que foi concluída com sucesso.
Pode parecer que Promise.any()
faz o mesmo que Promise.race()
, mas essas funções diferem na forma como lidam com promises que foram concluídas com erro. Promise.race()
retorna a primeira promise concluída, independentemente de ter sido concluída com erro ou não. Já Promise.any()
retorna a primeira promise que foi concluída com sucesso (se houver). Se todas as promises foram concluídas com erro, uma exceção do tipo AggregateError
é gerada:
const promise1 = new Promise((resolve, reject) => {
reject("erro na promise1");
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
reject("erro na promise2");
setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
.then((value) => console.log(value))
.catch((error) => console.log(error)); // AggregateError: All promises were rejected
Com a propriedade errors do tipo AggregateError
, é possível obter todas as falhas ocorridas nas promises em forma de array:
const promise1 = new Promise((resolve, reject) => {
reject("erro na promise1");
setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
reject("erro na promise2");
setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
.then((value) => console.log(value))
.catch((e) => console.log(e.errors)); // ["erro na promise1", "erro na promise2"]