Dominando Promises em JavaScript: Encadeamento, Promise.all e tratamento de erros
Tags: javascript, node, promises, api
Published: 2023-04-28 00:09:42

## Introdução
Este é o nosso último post da série Ecmascript 6 (posso ouvir um aahhhhhh daqui 😆). Nessa segunda parte, falaremos um pouco sobre encadeamento de promises, execução de múltiplas promises utilizando o `.then()` e uma dica de ouro ao utilizar promises. Vamos lá?!

## Promise.all
A função `Promise.all()` permite executar **<u>múltiplas promises simultaneamente</u>** e retornar **<u>um único valor</u>** quando todas elas forem resolvidas. Isso é útil quando você precisa executar várias tarefas assíncronas e só deseja prosseguir quando todas elas tiverem sido concluídas.

```javascript
const promise1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 100);
});

const promise2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('Promise 2 resolved');
  }, 200);
});

Promise.all([promise1, promise2])
  .then((results) => {
    console.log(results);
  });

// Result: ["Promise 1 resolved", "Promise 2 resolved"]
```
Vale destacar que, se qualquer uma das promises passadas for rejeitada, `Promise.all` assincronamente é rejeitada com o valor da promise rejeitada, independentemente se outras promises foram resolvidas.

```javascript
const promise1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('Promise 1 resolved');
  }, 100);
});

let promise2 = Promise.resolve("Promise 2 rejected");

Promise.all([promise1, promise2])
  .then((results) => {
    console.log(results);
  }).catch(e=>{
    console.log(e)
  });

// Result: Promise 2 rejected
```

## Encadeamento de promises
O encadeamento de promises permite executar **<u>uma série de tarefas assíncronas em uma ordem específica</u>**. Isso é útil quando você precisa executar uma tarefa após a conclusão de outra tarefa assíncrona. Para organizar essa sequência, utilizamos o manipulador `.then()`. É como se você chegasse para alguém dizendo: “Primeiramente, você precisa fazer isso, então faça aquilo, então faça esta outra coisa, então…, então…” e assim por diante.

**⚠️ Atenção**

_Não esqueça de escrever um retorno dentro do `.then()`, caso contrário, ele não irá funcionar corretamente._

Vamos para um exemplo. Suponha que você precise buscar as informações do usuário e, em seguida, buscar as informações de seus pedidos. Você pode usar o encadeamento de promises para executar essas duas tarefas em ordem, esperando que a primeira seja concluída antes de executar a segunda.

```javascript
const fetchUserData = (userId) => {
  return fetch(`https://api.example.com/users/${userId}`)
    .then(response => response.json());
};

const fetchUserOrders = (userId) => {
  return fetch(`https://api.example.com/users/${userId}/orders`)
    .then(response => response.json());
};

fetchUserData(1)
  .then(user => {
    console.log('Dados do usuário:', user);
    return fetchUserOrders(user.id);
  })
  .then(orders => {
    console.log('Pedidos do usuário:', orders);
  })
  .catch(error => {
    console.error('Ocorreu um erro:', error);
  });
```
A nossa saída será:

```terminal
Dados do usuário: 
user: {
	// informações do usuário
}

Pedidos do usuário: 
orders: [
	{
		// informações do pedido 1
	},
	{
		// informações do pedido 2
	}
]
```
## Erro handling

Uma regra de ouro é: “Seja responsável e faça o tratamento de erros corretamente”. Imagine o seguinte código abaixo:

```javascript
function makeRequest() {
  try {
    fetch('foo')
      .then(response => {
        const result = JSON.parse(response);
        console.log(result);
      })
  } catch (error) {
    console.log(error);
  }
}
```
O `try/catch` não irá se capaz de lidar com o erro se o `JSON.parse` falhar. Isso está acontecendo dentro da promise. Nós devemos chamar o .catch para conseguir tratar esse erro:

```javascript
function makeRequest() {
  try {
    fetch('foo')
      .then(response => {
        const result = JSON.parse(response);
        console.log(result);
      })
      .catch(error => {
        console.log(error);
      });
  } catch (error) {
    console.log(error);
  }
}
```
## Finally handler

Nós temos algo chamado finally handler, que é chamado independente se nossa promise foi resolvida ou rejeitada. Digamos que a promise abaixo seja rejeitada:

```javascript
fetch('foo')
	.then(() => {
		console.log("Consulta realizada com sucesso!");
	})
	.catch(() => {
		console.log("Erro ao consumir dados da API");
	})
	.finally(()=>{
	  console.log("Fim da requisição!")
	})
```
A nossa saída será:

```
"Erro ao consumir dados da API"
"Fim da requisição!"
```
## Conclusão
Bom pessoal, este é o fim da nossa série sobre Ecmascript 6. Terminamos essa série trazendo mais algumas informações sobre promises. Verificamos o funcionamento do `Promise.all`, que nos permite executar múltiplas promises simultaneamente. Também vimos a possibilidade de executar uma série de tarefas assíncronas em uma ordem específica, utilizando o encadeamento de promises. Além disso, lidamos com o tratamento de erros em promises de uma forma correta. Por fim, falamos sobre o finally, que nos permite executar algo independente se a nossa promise foi resolvida ou rejeitada. O que acho dessa série? Alguma sugestão? Nos vemos na próxima!

## Para saber mais

- [ECMAScript 6 Succinctly](https://www.syncfusion.com/succinctly-free-ebooks/ecmascript-6-succinctly)
- [JavaScript Async/Await Tutorial – Learn Callbacks, Promises, and Async/Await in JS by Making Ice Cream](https://www.freecodecamp.org/news/javascript-async-await-tutorial-learn-callbacks-promises-async-await-by-making-icecream)
- [Promise.all()](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)
- [What is Promise.all() in JavaScript?](https://www.educative.io/answers/what-is-promiseall-in-javascript)