Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 78 additions & 78 deletions 1-js/11-async/05-promise-api/article.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
# Promise API
# API de Promise

There are 6 static methods in the `Promise` class. We'll quickly cover their use cases here.
Existem 6 métodos estáticos na classe `Promise`. Vamos abordar rapidamente os seus casos de uso aqui.

## Promise.all

Let's say we want many promises to execute in parallel and wait until all of them are ready.
Digamos que queremos executar várias promessas em paralelo e esperar até que todas estejam prontas.

For instance, download several URLs in parallel and process the content once they are all done.
Por exemplo, baixar várias URLs em paralelo e processar o conteúdo assim que todas terminarem.

That's what `Promise.all` is for.
É para isso que serve o `Promise.all`.

The syntax is:
A sintaxe é:

```js
let promise = Promise.all(iterable);
```

`Promise.all` takes an iterable (usually, an array of promises) and returns a new promise.
O `Promise.all` recebe um iterável (geralmente, um array de promessas) e retorna uma nova promessa.

The new promise resolves when all listed promises are resolved, and the array of their results becomes its result.
A nova promessa é resolvida quando todas as promessas listadas são resolvidas, e o array dos resultados delas se torna o resultado dela.

For instance, the `Promise.all` below settles after 3 seconds, and then its result is an array `[1, 2, 3]`:
Por exemplo, o `Promise.all` abaixo é estabelecido depois de 3 segundos, e então seu resultado é um array `[1, 2, 3]`:

```js run
Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert); // 1,2,3 when promises are ready: each promise contributes an array member
]).then(alert); // 1,2,3 quando as promessas estiverem prontas: cada promessa contribui com um membro do array
```

Please note that the order of the resulting array members is the same as in its source promises. Even though the first promise takes the longest time to resolve, it's still first in the array of results.
Repare que a ordem dos membros do array resultante é a mesma das promessas de origem. Mesmo que a primeira promessa leve o maior tempo para ser resolvida, ela continua sendo a primeira no array de resultados.

A common trick is to map an array of job data into an array of promises, and then wrap that into `Promise.all`.
Um truque comum é mapear um array de dados em um array de promessas, e então envolver isso em um `Promise.all`.

For instance, if we have an array of URLs, we can fetch them all like this:
Por exemplo, se temos um array de URLs, podemos buscar todas assim:

```js run
let urls = [
Expand All @@ -43,17 +43,17 @@ let urls = [
'https://api.github.com/users/jeresig'
];

// map every url to the promise of the fetch
// mapeia cada url para a promessa do fetch
let requests = urls.map(url => fetch(url));

// Promise.all waits until all jobs are resolved
// Promise.all espera até que todos os trabalhos sejam resolvidos
Promise.all(requests)
.then(responses => responses.forEach(
response => alert(`${response.url}: ${response.status}`)
));
```

A bigger example with fetching user information for an array of GitHub users by their names (we could fetch an array of goods by their ids, the logic is identical):
Um exemplo maior, buscando informações de usuário para um array de usuários do GitHub pelos nomes deles (poderíamos buscar um array de produtos pelos ids deles, a lógica é idêntica):

```js run
let names = ['iliakan', 'remy', 'jeresig'];
Expand All @@ -62,22 +62,22 @@ let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));

Promise.all(requests)
.then(responses => {
// all responses are resolved successfully
// todas as respostas foram resolvidas com sucesso
for(let response of responses) {
alert(`${response.url}: ${response.status}`); // shows 200 for every url
alert(`${response.url}: ${response.status}`); // mostra 200 para cada url
}

return responses;
})
// map array of responses into an array of response.json() to read their content
// mapeia o array de respostas em um array de response.json() para ler o conteúdo delas
.then(responses => Promise.all(responses.map(r => r.json())))
// all JSON answers are parsed: "users" is the array of them
// todas as respostas JSON foram analisadas: "users" é o array delas
.then(users => users.forEach(user => alert(user.name)));
```

**If any of the promises is rejected, the promise returned by `Promise.all` immediately rejects with that error.**
**Se qualquer uma das promessas for rejeitada, a promessa retornada por `Promise.all` é imediatamente rejeitada com esse erro.**

For instance:
Por exemplo:

```js run
Promise.all([
Expand All @@ -89,20 +89,20 @@ Promise.all([
]).catch(alert); // Error: Whoops!
```

Here the second promise rejects in two seconds. That leads to an immediate rejection of `Promise.all`, so `.catch` executes: the rejection error becomes the outcome of the entire `Promise.all`.
Aqui a segunda promessa é rejeitada em dois segundos. Isso leva a uma rejeição imediata do `Promise.all`, então o `.catch` é executado: o erro da rejeição se torna o resultado de todo o `Promise.all`.

```warn header="In case of an error, other promises are ignored"
If one promise rejects, `Promise.all` immediately rejects, completely forgetting about the other ones in the list. Their results are ignored.
```warn header="Em caso de erro, as outras promessas são ignoradas"
Se uma promessa é rejeitada, o `Promise.all` é imediatamente rejeitado, esquecendo completamente das outras da lista. Os resultados delas são ignorados.

For example, if there are multiple `fetch` calls, like in the example above, and one fails, the others will still continue to execute, but `Promise.all` won't watch them anymore. They will probably settle, but their results will be ignored.
Por exemplo, se houver múltiplas chamadas `fetch`, como no exemplo acima, e uma delas falhar, as outras ainda vão continuar a ser executadas, mas o `Promise.all` não vai mais observá-las. Elas provavelmente serão estabelecidas, mas os resultados delas serão ignorados.

`Promise.all` does nothing to cancel them, as there's no concept of "cancellation" in promises. In [another chapter](info:fetch-abort) we'll cover `AbortController` that can help with that, but it's not a part of the Promise API.
O `Promise.all` não faz nada para cancelá-las, já que não existe o conceito de "cancelamento" em promessas. Em [outro capítulo](info:fetch-abort) vamos abordar o `AbortController`, que pode ajudar com isso, mas ele não é parte da API de Promise.
```

````smart header="`Promise.all(iterable)` allows non-promise \"regular\" values in `iterable`"
Normally, `Promise.all(...)` accepts an iterable (in most cases an array) of promises. But if any of those objects is not a promise, it's passed to the resulting array "as is".
````smart header="`Promise.all(iterable)` permite valores \"normais\" (não promessas) no `iterable`"
Normalmente, o `Promise.all(...)` aceita um iterável (na maioria dos casos, um array) de promessas. Mas se qualquer um desses objetos não for uma promessa, ele é passado "como está" para o array resultante.

For instance, here the results are `[1, 2, 3]`:
Por exemplo, aqui os resultados são `[1, 2, 3]`:

```js run
Promise.all([
Expand All @@ -114,31 +114,31 @@ Promise.all([
]).then(alert); // 1, 2, 3
```

So we are able to pass ready values to `Promise.all` where convenient.
Então conseguimos passar valores já prontos para o `Promise.all` quando for conveniente.
````

## Promise.allSettled

[recent browser="new"]

`Promise.all` rejects as a whole if any promise rejects. That's good for "all or nothing" cases, when we need *all* results successful to proceed:
O `Promise.all` rejeita por completo se qualquer promessa for rejeitada. Isso é bom para casos do tipo "tudo ou nada", quando precisamos que *todos* os resultados sejam bem-sucedidos para prosseguir:

```js
Promise.all([
fetch('/template.html'),
fetch('/style.css'),
fetch('/data.json')
]).then(render); // render method needs results of all fetches
]).then(render); // o método render precisa dos resultados de todas as requisições
```

`Promise.allSettled` just waits for all promises to settle, regardless of the result. The resulting array has:
O `Promise.allSettled` apenas espera que todas as promessas sejam estabelecidas, independentemente do resultado. O array resultante tem:

- `{status:"fulfilled", value:result}` for successful responses,
- `{status:"rejected", reason:error}` for errors.
- `{status:"fulfilled", value:result}` para respostas bem-sucedidas,
- `{status:"rejected", reason:error}` para erros.

For example, we'd like to fetch the information about multiple users. Even if one request fails, we're still interested in the others.
Por exemplo, gostaríamos de buscar as informações de vários usuários. Mesmo que uma requisição falhe, ainda estamos interessados nas outras.

Let's use `Promise.allSettled`:
Vamos usar o `Promise.allSettled`:

```js run
let urls = [
Expand All @@ -160,20 +160,20 @@ Promise.allSettled(urls.map(url => fetch(url)))
});
```

The `results` in the line `(*)` above will be:
O `results` na linha `(*)` acima será:
```js
[
{status: 'fulfilled', value: ...response...},
{status: 'fulfilled', value: ...response...},
{status: 'rejected', reason: ...error object...}
{status: 'fulfilled', value: ...resposta...},
{status: 'fulfilled', value: ...resposta...},
{status: 'rejected', reason: ...objeto de erro...}
]
```

So for each promise we get its status and `value/error`.
Então, para cada promessa, obtemos o status e o `value`/`reason` dela.

### Polyfill

If the browser doesn't support `Promise.allSettled`, it's easy to polyfill:
Se o navegador não suportar `Promise.allSettled`, é fácil fazer um polyfill:

```js
if (!Promise.allSettled) {
Expand All @@ -188,23 +188,23 @@ if (!Promise.allSettled) {
}
```

In this code, `promises.map` takes input values, turns them into promises (just in case a non-promise was passed) with `p => Promise.resolve(p)`, and then adds `.then` handler to every one.
Nesse código, `promises.map` pega os valores de entrada, os transforma em promessas (só por garantia, caso algo que não seja uma promessa tenha sido passado) com `p => Promise.resolve(p)`, e então adiciona um tratador `.then` a cada uma.

That handler turns a successful result `value` into `{status:'fulfilled', value}`, and an error `reason` into `{status:'rejected', reason}`. That's exactly the format of `Promise.allSettled`.
Esse tratador transforma um resultado `value` bem-sucedido em `{status:'fulfilled', value}`, e um erro `reason` em `{status:'rejected', reason}`. Esse é exatamente o formato do `Promise.allSettled`.

Now we can use `Promise.allSettled` to get the results of *all* given promises, even if some of them reject.
Agora podemos usar o `Promise.allSettled` para obter os resultados de *todas* as promessas dadas, mesmo que algumas delas sejam rejeitadas.

## Promise.race

Similar to `Promise.all`, but waits only for the first settled promise and gets its result (or error).
Parecido com o `Promise.all`, mas espera apenas pela primeira promessa estabelecida e pega o resultado dela (ou erro).

The syntax is:
A sintaxe é:

```js
let promise = Promise.race(iterable);
```

For instance, here the result will be `1`:
Por exemplo, aqui o resultado será `1`:

```js run
Promise.race([
Expand All @@ -214,20 +214,20 @@ Promise.race([
]).then(alert); // 1
```

The first promise here was fastest, so it became the result. After the first settled promise "wins the race", all further results/errors are ignored.
A primeira promessa aqui foi a mais rápida, então ela se tornou o resultado. Depois que a primeira promessa estabelecida "vence a corrida", todos os outros resultados/erros são ignorados.


## Promise.any

Similar to `Promise.race`, but waits only for the first fulfilled promise and gets its result. If all of the given promises are rejected, then the returned promise is rejected with [`AggregateError`](mdn:js/AggregateError) - a special error object that stores all promise errors in its `errors` property.
Parecido com o `Promise.race`, mas espera apenas pela primeira promessa cumprida e pega o resultado dela. Se todas as promessas dadas forem rejeitadas, então a promessa retornada é rejeitada com [`AggregateError`](mdn:js/AggregateError) - um objeto de erro especial que guarda todos os erros das promessas na sua propriedade `errors`.

The syntax is:
A sintaxe é:

```js
let promise = Promise.any(iterable);
```

For instance, here the result will be `1`:
Por exemplo, aqui o resultado será `1`:

```js run
Promise.any([
Expand All @@ -237,9 +237,9 @@ Promise.any([
]).then(alert); // 1
```

The first promise here was fastest, but it was rejected, so the second promise became the result. After the first fulfilled promise "wins the race", all further results are ignored.
A primeira promessa aqui foi a mais rápida, mas foi rejeitada, então a segunda promessa se tornou o resultado. Depois que a primeira promessa cumprida "vence a corrida", todos os outros resultados são ignorados.

Here's an example when all promises fail:
Aqui está um exemplo de quando todas as promessas falham:

```js run
Promise.any([
Expand All @@ -252,27 +252,27 @@ Promise.any([
});
```

As you can see, error objects for failed promises are available in the `errors` property of the `AggregateError` object.
Como você pode ver, os objetos de erro das promessas que falharam ficam disponíveis na propriedade `errors` do objeto `AggregateError`.

## Promise.resolve/reject

Methods `Promise.resolve` and `Promise.reject` are rarely needed in modern code, because `async/await` syntax (we'll cover it [a bit later](info:async-await)) makes them somewhat obsolete.
Os métodos `Promise.resolve` e `Promise.reject` raramente são necessários no código moderno, porque a sintaxe `async/await` (vamos abordar isso [um pouco mais adiante](info:async-await)) os torna meio obsoletos.

We cover them here for completeness and for those who can't use `async/await` for some reason.
Vamos abordá-los aqui por completude, e para quem não pode usar `async/await` por algum motivo.

### Promise.resolve

`Promise.resolve(value)` creates a resolved promise with the result `value`.
`Promise.resolve(value)` cria uma promessa resolvida com o resultado `value`.

Same as:
O mesmo que:

```js
let promise = new Promise(resolve => resolve(value));
```

The method is used for compatibility, when a function is expected to return a promise.
O método é usado para compatibilidade, quando se espera que uma função retorne uma promessa.

For example, the `loadCached` function below fetches a URL and remembers (caches) its content. For future calls with the same URL it immediately gets the previous content from cache, but uses `Promise.resolve` to make a promise of it, so the returned value is always a promise:
Por exemplo, a função `loadCached` abaixo busca uma URL e lembra (guarda em cache) o seu conteúdo. Para chamadas futuras com a mesma URL, ela pega imediatamente o conteúdo anterior do cache, mas usa o `Promise.resolve` para fazer disso uma promessa, de forma que o valor retornado seja sempre uma promessa:

```js
let cache = new Map();
Expand All @@ -293,31 +293,31 @@ function loadCached(url) {
}
```

We can write `loadCached(url).then(…)`, because the function is guaranteed to return a promise. We can always use `.then` after `loadCached`. That's the purpose of `Promise.resolve` in the line `(*)`.
Podemos escrever `loadCached(url).then(…)`, porque a função garante retornar uma promessa. Podemos sempre usar `.then` depois de `loadCached`. Esse é o propósito do `Promise.resolve` na linha `(*)`.

### Promise.reject

`Promise.reject(error)` creates a rejected promise with `error`.
`Promise.reject(error)` cria uma promessa rejeitada com `error`.

Same as:
O mesmo que:

```js
let promise = new Promise((resolve, reject) => reject(error));
```

In practice, this method is almost never used.
Na prática, esse método quase nunca é usado.

## Summary
## Resumo

There are 6 static methods of `Promise` class:
Existem 6 métodos estáticos da classe `Promise`:

1. `Promise.all(promises)` -- waits for all promises to resolve and returns an array of their results. If any of the given promises rejects, it becomes the error of `Promise.all`, and all other results are ignored.
2. `Promise.allSettled(promises)` (recently added method) -- waits for all promises to settle and returns their results as an array of objects with:
- `status`: `"fulfilled"` or `"rejected"`
- `value` (if fulfilled) or `reason` (if rejected).
3. `Promise.race(promises)` -- waits for the first promise to settle, and its result/error becomes the outcome.
4. `Promise.any(promises)` (recently added method) -- waits for the first promise to fulfill, and its result becomes the outcome. If all of the given promises are rejected, [`AggregateError`](mdn:js/AggregateError) becomes the error of `Promise.any`.
5. `Promise.resolve(value)` -- makes a resolved promise with the given value.
6. `Promise.reject(error)` -- makes a rejected promise with the given error.
1. `Promise.all(promises)` -- espera que todas as promessas sejam resolvidas e retorna um array dos resultados delas. Se qualquer uma das promessas dadas for rejeitada, isso se torna o erro do `Promise.all`, e todos os outros resultados são ignorados.
2. `Promise.allSettled(promises)` (método adicionado recentemente) -- espera que todas as promessas sejam estabelecidas e retorna os resultados delas como um array de objetos com:
- `status`: `"fulfilled"` ou `"rejected"`
- `value` (se cumprida) ou `reason` (se rejeitada).
3. `Promise.race(promises)` -- espera que a primeira promessa seja estabelecida, e o resultado/erro dela se torna o resultado final.
4. `Promise.any(promises)` (método adicionado recentemente) -- espera que a primeira promessa seja resolvida, e o resultado dela se torna o resultado final. Se todas as promessas dadas forem rejeitadas, [`AggregateError`](mdn:js/AggregateError) se torna o erro do `Promise.any`.
5. `Promise.resolve(value)` -- cria uma promessa resolvida com o valor dado.
6. `Promise.reject(error)` -- cria uma promessa rejeitada com o erro dado.

Of all these, `Promise.all` is probably the most common in practice.
De todos esses, o `Promise.all` é provavelmente o mais comum na prática.