Skip to content
Merged
Show file tree
Hide file tree
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
14 changes: 7 additions & 7 deletions 1-js/11-async/08-async-await/01-rewrite-async/solution.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

The notes are below the code:
As notas estão abaixo do código:

```js run
async function loadJson(url) { // (1)
Expand All @@ -17,17 +17,17 @@ loadJson('https://javascript.info/no-such-user.json')
.catch(alert); // Error: 404 (4)
```

Notes:
Notas:

1. The function `loadJson` becomes `async`.
2. All `.then` inside are replaced with `await`.
3. We can `return response.json()` instead of awaiting for it, like this:
1. A função `loadJson` se torna `async`.
2. Todos os `.then` dentro dela são substituídos por `await`.
3. Podemos fazer `return response.json()` em vez de esperar por ele com `await`, assim:

```js
if (response.status == 200) {
return response.json(); // (3)
}
```

Then the outer code would have to `await` for that promise to resolve. In our case it doesn't matter.
4. The error thrown from `loadJson` is handled by `.catch`. We can't use `await loadJson(…)` there, because we're not in an `async` function.
Então o código externo teria que usar `await` para essa promessa ser resolvida. No nosso caso, não faz diferença.
4. O erro lançado por `loadJson` é tratado pelo `.catch`. Não podemos usar `await loadJson(…)` ali, porque não estamos dentro de uma função `async`.
4 changes: 2 additions & 2 deletions 1-js/11-async/08-async-await/01-rewrite-async/task.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# Rewrite using async/await
# Reescreva usando async/await

Rewrite this example code from the chapter <info:promise-chaining> using `async/await` instead of `.then/catch`:
Reescreva este código de exemplo do capítulo <info:promise-chaining> usando `async/await` em vez de `.then/catch`:

```js run
function loadJson(url) {
Expand Down
16 changes: 8 additions & 8 deletions 1-js/11-async/08-async-await/02-rewrite-async-2/solution.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

There are no tricks here. Just replace `.catch` with `try..catch` inside `demoGithubUser` and add `async/await` where needed:
Não tem nenhum truque aqui. Só substitua o `.catch` por `try..catch` dentro de `demoGithubUser` e adicione `async/await` onde for necessário:

```js run
class HttpError extends Error {
Expand All @@ -19,29 +19,29 @@ async function loadJson(url) {
}
}

// Ask for a user name until github returns a valid user
// Pede um nome de usuário até o github retornar um usuário válido
async function demoGithubUser() {

let user;
while(true) {
let name = prompt("Enter a name?", "iliakan");
let name = prompt("Digite um nome:", "iliakan");

try {
user = await loadJson(`https://api.github.com/users/${name}`);
break; // no error, exit loop
break; // sem erro, sai do laço
} catch(err) {
if (err instanceof HttpError && err.response.status == 404) {
// loop continues after the alert
alert("No such user, please reenter.");
// o laço continua depois do alert
alert("Esse usuário não existe, digite de novo.");
} else {
// unknown error, rethrow
// erro desconhecido, relança
throw err;
}
}
}


alert(`Full name: ${user.name}.`);
alert(`Nome completo: ${user.name}.`);
return user;
}

Expand Down
14 changes: 7 additions & 7 deletions 1-js/11-async/08-async-await/02-rewrite-async-2/task.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

# Rewrite "rethrow" with async/await
# Reescreva o "relançamento" com async/await

Below you can find the "rethrow" example. Rewrite it using `async/await` instead of `.then/catch`.
Abaixo você pode encontrar o exemplo de "relançamento". Reescreva-o usando `async/await` em vez de `.then/catch`.

And get rid of the recursion in favour of a loop in `demoGithubUser`: with `async/await` that becomes easy to do.
E se livre da recursão, usando um laço em `demoGithubUser`: com `async/await` isso fica fácil de fazer.

```js run
class HttpError extends Error {
Expand All @@ -25,18 +25,18 @@ function loadJson(url) {
});
}

// Ask for a user name until github returns a valid user
// Pede um nome de usuário até o github retornar um usuário válido
function demoGithubUser() {
let name = prompt("Enter a name?", "iliakan");
let name = prompt("Digite um nome:", "iliakan");

return loadJson(`https://api.github.com/users/${name}`)
.then(user => {
alert(`Full name: ${user.name}.`);
alert(`Nome completo: ${user.name}.`);
return user;
})
.catch(err => {
if (err instanceof HttpError && err.response.status == 404) {
alert("No such user, please reenter.");
alert("Esse usuário não existe, digite de novo.");
return demoGithubUser();
} else {
throw err;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

That's the case when knowing how it works inside is helpful.
Esse é um caso em que saber como funciona por dentro ajuda.

Just treat `async` call as promise and attach `.then` to it:
Basta tratar a chamada `async` como uma promessa e anexar `.then` a ela:
```js run
async function wait() {
await new Promise(resolve => setTimeout(resolve, 1000));
Expand All @@ -10,7 +10,7 @@ async function wait() {
}

function f() {
// shows 10 after 1 second
// mostra 10 depois de 1 segundo
*!*
wait().then(result => alert(result));
*/!*
Expand Down
12 changes: 6 additions & 6 deletions 1-js/11-async/08-async-await/03-async-from-regular/task.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# Call async from non-async
# Chame async a partir de não-async

We have a "regular" function called `f`. How can you call the `async` function `wait()` and use its result inside of `f`?
Temos uma função "comum" chamada `f`. Como você pode chamar a função `async` `wait()` e usar o resultado dela dentro de `f`?

```js
async function wait() {
Expand All @@ -11,10 +11,10 @@ async function wait() {
}

function f() {
// ...what should you write here?
// we need to call async wait() and wait to get 10
// remember, we can't use "await"
// ...o que você deveria escrever aqui?
// precisamos chamar a wait() async e esperar para obter o 10
// lembre-se, não podemos usar "await"
}
```

P.S. The task is technically very simple, but the question is quite common for developers new to async/await.
P.S. A tarefa é tecnicamente bem simples, mas a pergunta é bem comum entre desenvolvedores novos no async/await.
48 changes: 24 additions & 24 deletions 1-js/11-async/08-async-await/04-promise-all-failure/solution.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,52 @@

The root of the problem is that `Promise.all` immediately rejects when one of its promises rejects, but it do nothing to cancel the other promises.
A raiz do problema é que o `Promise.all` rejeita imediatamente quando uma das suas promessas é rejeitada, mas ele não faz nada para cancelar as outras promessas.

In our case, the second query fails, so `Promise.all` rejects, and the `try...catch` block catches this error.Meanwhile, other promises are *not affected* - they independently continue their execution. In our case, the third query throws an error of its own after a bit of time. And that error is never caught, we can see it in the console.
No nosso caso, a segunda consulta falha, então o `Promise.all` rejeita, e o bloco `try...catch` captura esse erro. Enquanto isso, as outras promessas *não são afetadas* - elas continuam a execução de forma independente. No nosso caso, a terceira consulta lança um erro próprio depois de um tempo. E esse erro nunca é capturado, podemos ver isso no console.

The problem is especially dangerous in server-side environments, such as Node.js, when an uncaught error may cause the process to crash.
O problema é especialmente perigoso em ambientes do lado do servidor, como o Node.js, quando um erro não capturado pode fazer o processo ser encerrado.

How to fix it?
Como corrigir isso?

An ideal solution would be to cancel all unfinished queries when one of them fails. This way we avoid any potential errors.
Uma solução ideal seria cancelar todas as consultas não finalizadas quando uma delas falha. Dessa forma, evitamos qualquer erro em potencial.

However, the bad news is that service calls (such as `database.query`) are often implemented by a 3rd-party library which doesn't support cancellation. Then there's no way to cancel a call.
Porém, a má notícia é que chamadas de serviço (como `database.query`) são frequentemente implementadas por uma biblioteca de terceiros que não suporta cancelamento. Nesse caso, não há como cancelar uma chamada.

As an alternative, we can write our own wrapper function around `Promise.all` which adds a custom `then/catch` handler to each promise to track them: results are gathered and, if an error occurs, all subsequent promises are ignored.
Como alternativa, podemos escrever nossa própria função que envolve o `Promise.all` e adiciona um tratador `then/catch` personalizado a cada promessa para rastreá-las: os resultados são reunidos e, se ocorrer um erro, todas as promessas seguintes são ignoradas.

```js
function customPromiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let resultsCount = 0;
let hasError = false; // we'll set it to true upon first error
let hasError = false; // vamos deixar true no primeiro erro

promises.forEach((promise, index) => {
promise
.then(result => {
if (hasError) return; // ignore the promise if already errored
if (hasError) return; // ignora a promessa se já deu erro
results[index] = result;
resultsCount++;
if (resultsCount === promises.length) {
resolve(results); // when all results are ready - successs
resolve(results); // quando todos os resultados estão prontos - sucesso
}
})
.catch(error => {
if (hasError) return; // ignore the promise if already errored
hasError = true; // wops, error!
reject(error); // fail with rejection
if (hasError) return; // ignora a promessa se já deu erro
hasError = true; // opa, erro!
reject(error); // falha com rejeição
});
});
});
}
```

This approach has an issue of its own - it's often undesirable to `disconnect()` when queries are still in the process.
Essa abordagem tem um problema próprio - geralmente não é desejável fazer `disconnect()` enquanto as consultas ainda estão em andamento.

It may be important that all queries complete, especially if some of them make important updates.
Pode ser importante que todas as consultas se completem, especialmente se algumas delas fazem atualizações importantes.

So we should wait until all promises are settled before going further with the execution and eventually disconnecting.
Então deveríamos esperar até que todas as promessas sejam estabelecidas antes de seguir com a execução e, por fim, desconectar.

Here's another implementation. It behaves similar to `Promise.all` - also resolves with the first error, but waits until all promises are settled.
Aqui está outra implementação. Ela se comporta de forma parecida com o `Promise.all` - também rejeita com o primeiro erro, mas espera até que todas as promessas sejam estabelecidas.

```js
function customPromiseAllWait(promises) {
Expand Down Expand Up @@ -80,16 +80,16 @@ function customPromiseAllWait(promises) {
}
```

Now `await customPromiseAllWait(...)` will stall the execution until all queries are processed.
Agora `await customPromiseAllWait(...)` vai suspender a execução até que todas as consultas sejam processadas.

This is a more reliable approach, as it guarantees a predictable execution flow.
Essa é uma abordagem mais confiável, já que garante um fluxo de execução previsível.

Lastly, if we'd like to process all errors, we can use either use `Promise.allSettled` or write a wrapper around it to gathers all errors in a single [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) object and rejects with it.
Por fim, se quisermos processar todos os erros, podemos usar o `Promise.allSettled` ou escrever uma função que o envolve e reúne todos os erros em um único objeto [AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError) e rejeita com ele.

```js
// wait for all promises to settle
// return results if no errors
// throw AggregateError with all errors if any
// espera todas as promessas serem estabelecidas
// retorna os resultados se não houver erros
// lança AggregateError com todos os erros, se houver
function allOrAggregateError(promises) {
return Promise.allSettled(promises).then(results => {
const errors = [];
Expand All @@ -104,7 +104,7 @@ function allOrAggregateError(promises) {
});

if (errors.length > 0) {
throw new AggregateError(errors, 'One or more promises failed');
throw new AggregateError(errors, 'Uma ou mais promessas falharam');
}

return values;
Expand Down
38 changes: 19 additions & 19 deletions 1-js/11-async/08-async-await/04-promise-all-failure/task.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@

# Dangerous Promise.all
# Promise.all perigoso

`Promise.all` is a great way to parallelize multiple operations. It's especially useful when we need to make parallel requests to multiple services.
O `Promise.all` é uma ótima forma de paralelizar múltiplas operações. É especialmente útil quando precisamos fazer requisições em paralelo para vários serviços.

However, there's a hidden danger. We'll see an example in this task and explore how to avoid it.
Porém, existe um perigo escondido. Vamos ver um exemplo nessa tarefa e explorar como evitá-lo.

Let's say we have a connection to a remote service, such as a database.
Digamos que temos uma conexão com um serviço remoto, como um banco de dados.

There're two functions: `connect()` and `disconnect()`.
Existem duas funções: `connect()` e `disconnect()`.

When connected, we can send requests using `database.query(...)` - an async function which usually returns the result but also may throw an error.
Quando conectados, podemos enviar requisições usando `database.query(...)` - uma função async que geralmente retorna o resultado, mas também pode lançar um erro.

Here's a simple implementation:
Aqui está uma implementação simples:

```js
let database;
Expand All @@ -28,21 +28,21 @@ function disconnect() {
database = null;
}

// intended usage:
// uso pretendido:
// connect()
// ...
// database.query(true) to emulate a successful call
// database.query(false) to emulate a failed call
// database.query(true) para simular uma chamada bem-sucedida
// database.query(false) para simular uma chamada que falha
// ...
// disconnect()
```

Now here's the problem.
Agora aqui está o problema.

We wrote the code to connect and send 3 queries in parallel (all of them take different time, e.g. 100, 200 and 300ms), then disconnect:
Escrevemos o código para conectar e enviar 3 consultas em paralelo (todas elas levam tempos diferentes, por exemplo 100, 200 e 300ms), e então desconectar:

```js
// Helper function to call async function `fn` after `ms` milliseconds
// Função auxiliar para chamar a função async `fn` depois de `ms` milissegundos
function delay(fn, ms) {
return new Promise((resolve, reject) => {
setTimeout(() => fn().then(resolve, reject), ms);
Expand All @@ -54,16 +54,16 @@ async function run() {

try {
await Promise.all([
// these 3 parallel jobs take different time: 100, 200 and 300 ms
// we use the `delay` helper to achieve this effect
// esses 3 trabalhos em paralelo levam tempos diferentes: 100, 200 e 300 ms
// usamos o auxiliar `delay` para conseguir esse efeito
*!*
delay(() => database.query(true), 100),
delay(() => database.query(false), 200),
delay(() => database.query(false), 300)
*/!*
]);
} catch(error) {
console.log('Error handled (or was it?)');
console.log('Erro tratado (ou será que foi?)');
}

disconnect();
Expand All @@ -72,8 +72,8 @@ async function run() {
run();
```

Two of these queries happen to be unsuccessful, but we're smart enough to wrap the `Promise.all` call into a `try..catch` block.
Duas dessas consultas acabam não tendo sucesso, mas somos espertos o bastante para envolver a chamada do `Promise.all` em um bloco `try..catch`.

However, this doesn't help! This script actually leads to an uncaught error in console!
Porém, isso não ajuda! Esse script na verdade leva a um erro não capturado no console!

Why? How to avoid it?
Por quê? Como evitar isso?
Loading