Neste tutorial, eu vou te ensinar sobre o Promise.all()
e Promise.allSettled()
métodos e como você pode usá-los para trabalhar com várias promessas.
Usando o Promise.all()
Método
O Promise
objeto tem três métodos úteis chamados then()
, catch()
e finally()
que você pode usar para executar métodos de retorno de chamada quando a promessa for estabelecida.
O Promise.all()
method é um método estático, o que significa que ele pertence a toda a classe em vez de estar vinculado a qualquer instância específica da classe. Ele aceita um iterável de promessas como entrada e retorna um único Promise
objeto.
Como mencionei anteriormente, o Promise.all()
O método retorna uma nova promessa. Essa nova promessa resolverá para uma matriz de valores de promessas estabelecidas se todas as promessas passadas para o método tiverem sido resolvidas com sucesso. Essa nova promessa também será liquidada com uma rejeição assim que uma das promessas passadas for rejeitada.
Todas as promessas são resolvidas com sucesso
Aqui está um exemplo do Promise.all()
método onde todas as promessas foram resolvidas com sucesso:
1 |
const promise_a = new Promise((resolve) => { |
2 |
setTimeout(() => { |
3 |
resolve('Loaded Textures'); |
4 |
}, 3000); |
5 |
});
|
6 |
|
7 |
const promise_b = new Promise((resolve) => { |
8 |
setTimeout(() => { |
9 |
resolve('Loaded Music'); |
10 |
}, 2000); |
11 |
});
|
12 |
|
13 |
const promise_c = new Promise((resolve) => { |
14 |
setTimeout(() => { |
15 |
resolve('Loaded Dialogues'); |
16 |
}, 4000); |
17 |
});
|
18 |
|
19 |
|
20 |
const promessas = [ |
21 |
promise_a, promise_b, promise_c |
22 |
];
|
23 |
|
24 |
console.log('Hello, Promises!'); |
25 |
|
26 |
Promise.all(promises).then((values) => { |
27 |
console.log(values); |
28 |
console.log('Start the Game!'); |
29 |
});
|
30 |
|
31 |
/* Output
|
32 |
|
33 |
19:32:06 Hello, Promises!
|
34 |
19:32:10 Array(3) [ "Loaded Textures", "Loaded Music", "Loaded Dialogues" ]
|
35 |
19:32:10 Start the Game!
|
36 |
|
37 |
*/
|
Nossa declaração antes da chamada para o Promise.all()
método foi registrado às 19:32:06. Além disso, nossa terceira promessa chamada promise_c
leva mais tempo para resolver e resolve após 4 segundos. Isso significa que a promessa retornada pela chamada ao all()
O método também deve levar 4 segundos para ser resolvido. Podemos verificar se leva 4 segundos para resolver passando uma função de retorno de chamada para o then()
método.
Outra coisa importante a observar aqui é que a matriz retornada de valores preenchidos contém esses valores na mesma ordem em que passamos as promessas para o Promise.all()
método. A promessa nomeada promise_b
resolve o mais rápido, em 2 segundos. No entanto, seu valor resolvido ainda está na segunda posição na matriz retornada. Isso corresponde à posição em que passamos a promessa ao Promise.all()
método.
Essa manutenção da ordem pode ser muito útil em certas situações. Por exemplo, digamos que você esteja buscando informações sobre o clima em dez cidades diferentes usando dez promessas diferentes. Todos eles não serão resolvidos ao mesmo tempo, e a ordem em que serão resolvidos provavelmente não será conhecida de antemão. No entanto, se você souber que os dados são retornados na mesma ordem em que você passou a promessa, poderá atribuí-los adequadamente para manipulação posterior.
Uma promessa rejeitada
Aqui está um exemplo onde uma das promessas é rejeitada:
1 |
const promise_a = new Promise((resolve) => { |
2 |
setTimeout(() => { |
3 |
resolve('Loaded Textures'); |
4 |
}, 3000); |
5 |
});
|
6 |
|
7 |
const promise_b = new Promise((resolve, reject) => { |
8 |
setTimeout(() => { |
9 |
reject(new Error('Could Not Load Music')); |
10 |
}, 2000); |
11 |
});
|
12 |
|
13 |
const promise_c = new Promise((resolve) => { |
14 |
setTimeout(() => { |
15 |
resolve('Loaded Dialogues'); |
16 |
}, 4000); |
17 |
});
|
18 |
|
19 |
|
20 |
const promessas = [ |
21 |
promise_a, promise_b, promise_c |
22 |
];
|
23 |
|
24 |
console.log('Hello, Promises!'); |
25 |
|
26 |
Promise.all(promises).catch((error) => { |
27 |
console.error(error.message); |
28 |
console.log('Stop the Game!'); |
29 |
});
|
30 |
|
31 |
/* Output
|
32 |
|
33 |
20:03:43 Hello, Promises!
|
34 |
20:03:45 Could Not Load Music
|
35 |
20:03:45 Stop the Game!
|
36 |
|
37 |
*/
|
Mais uma vez, nossa declaração antes da chamada para o all()
método foi registrado às 20:03:43. No entanto, nossa segunda promessa promise_b
resolvido com uma rejeição desta vez. Nós podemos ver isso promise_b
foi rejeitado após 2 segundos. Isso significa que a promessa retornada pelo all()
método também deve rejeitar após 2 segundos com o mesmo erro que o nosso promise_b
. É evidente a partir da saída que isso é exatamente o que aconteceu.
Uso com o await
Palavra-chave
Você provavelmente já sabe que o await
A palavra-chave é usada para aguardar a resolução de uma promessa antes de prosseguir. Também sabemos que o all()
O método retorna uma única promessa. Isso significa que podemos usar await
juntamente com uma chamada para o Promise.all()
método.
A única coisa a ter em mente é que desde await
só é válido dentro de funções e módulos assíncronos, teremos que envolver nosso código dentro de uma função assíncrona, conforme mostrado abaixo:
1 |
function create_promise(data, duration) { |
2 |
return new Promise((resolve) => { |
3 |
setTimeout(() => { |
4 |
resolve(data); |
5 |
}, duration); |
6 |
});
|
7 |
}
|
8 |
|
9 |
const promise_a = create_promise("Loaded Textures", 3000); |
10 |
const promise_b = create_promise("Loaded Music", 2000); |
11 |
const promise_c = create_promise("Loaded Dialogue", 4000); |
12 |
|
13 |
const my_promises = [promise_a, promise_b, promise_c]; |
14 |
|
15 |
async function result_from_promises(promises) { |
16 |
let loading_status = await Promise.all(promises); |
17 |
console.log(loading_status); |
18 |
}
|
19 |
|
20 |
result_from_promises(my_promises); |
21 |
|
22 |
/* Outputs
|
23 |
|
24 |
08:50:43 Hello, Promises!
|
25 |
08:50:47 Array(3) [ "Loaded Textures", "Loaded Music", "Loaded Dialogue" ]
|
26 |
|
27 |
*/
|
Desta vez, definimos uma função chamada create_promise()
que cria promessas para nós com base nos dados e duração fornecidos. nosso assíncrono result_from_promises()
função usa o await
palavra-chave para aguardar a resolução das promessas.
Usando o Promise.allSettled()
Método
Faz sentido usar o Promise.all()
método quando você deseja apenas prosseguir depois que todas as promessas forem resolvidas com êxito. Isso pode ser útil quando você está carregando recursos para um jogo, por exemplo.
No entanto, digamos que você esteja obtendo informações sobre o clima em diferentes cidades. Nesse caso, faria sentido para você enviar as informações meteorológicas para quaisquer cidades onde a busca dos dados foi bem-sucedida e gerar uma mensagem de erro quando a busca dos dados falhou.
O Promise.allSettled()
método funciona melhor neste caso. Este método espera que todas as promessas passadas sejam liquidadas com uma resolução ou com uma rejeição. A promessa retornada por esse método contém uma matriz de objetos que contêm informações sobre o resultado de cada promessa.
1 |
function create_promise(city) { |
2 |
let random_number = Math.random(); |
3 |
|
4 |
let duration = Math.floor(Math.random()*5)*1000; |
5 |
|
6 |
return new Promise((resolve, reject) => { |
7 |
if (random_number < 0.8) { |
8 |
setTimeout(() => { |
9 |
resolve(`Show weather in ${city}`); |
10 |
}, duration); |
11 |
} else { |
12 |
setTimeout(() => { |
13 |
reject(`Data unavailable for ${city}`); |
14 |
}, duration); |
15 |
}
|
16 |
});
|
17 |
}
|
18 |
|
19 |
const promise_a = create_promise("Delhi"); |
20 |
const promise_b = create_promise("London"); |
21 |
const promise_c = create_promise("Sydney"); |
22 |
|
23 |
const my_promises = [create_promise("Delhi"), create_promise("London"), create_promise("Sydney"), create_promise("Rome"), create_promise("Las Vegas")]; |
24 |
|
25 |
async function result_from_promises(promises) { |
26 |
let loading_status = await Promise.allSettled(promises); |
27 |
console.log(loading_status); |
28 |
}
|
29 |
|
30 |
result_from_promises(my_promises); |
31 |
|
32 |
/* Outputs
|
33 |
|
34 |
[
|
35 |
{
|
36 |
"status": "fulfilled",
|
37 |
"value": "Show weather in Delhi"
|
38 |
},
|
39 |
{
|
40 |
"status": "fulfilled",
|
41 |
"value": "Show weather in London"
|
42 |
},
|
43 |
{
|
44 |
"status": "fulfilled",
|
45 |
"value": "Show weather in Sydney"
|
46 |
},
|
47 |
{
|
48 |
"status": "rejected",
|
49 |
"reason": "Data unavailable for Rome"
|
50 |
},
|
51 |
{
|
52 |
"status": "fulfilled",
|
53 |
"value": "Show weather in Las Vegas"
|
54 |
}
|
55 |
]
|
56 |
|
57 |
*/
|
Como você pode ver, cada objeto em nosso array contém um status
propriedade para nos informar se a promessa foi cumprida ou rejeitada. No caso de promessas cumpridas, contém o valor resolvido no value
propriedade. No caso de promessas rejeitadas, contém o motivo da rejeição no reason
propriedade.
Pensamentos finais
Aprendemos sobre dois métodos úteis do Promise
classe que permite trabalhar com várias promessas de uma só vez. O Promise.all()
O método é útil quando você deseja parar de esperar que outras promessas sejam liquidadas assim que uma delas for rejeitada. O Promise.allSettled()
O método é útil quando você deseja aguardar a liquidação de todas as promessas, independentemente de seu status de resolução ou rejeição.