Entendendo Promises no JavaScript
Tags: javascript, webdev, node, typescript
Published: 2021-07-10 04:21:32

Ao trabalhar com chamadas assíncronas no JavaScript em algum momento você já se deparou com uma promise, talvez até sem saber exatamente que estava utilizando uma, mas por de trás dos panos ela estava lá.

Uma promise é o objeto retornado de uma chamada assíncrona que possui a promessa de um valor, seja ele um valor futuro, imediato ou que nunca existirá. São exatamente estes os estados de uma promise:

* ***pending*** (pendente): ainda não foi finalizada, mas também não foi rejeitada
* ***fulfilled*** (realizada): sucesso na operação.
* ***rejected*** (rejeitado):  falha na operação.

Quando uma promise é realizada significa que a chamada assíncrona foi finalizada e não foi encontrado nenhum erro na sua execução, neste momento ela terá um valor, caso essa chamada seja rejeitada, ela terá um motivo (erro).

### Criação da promise

```javascript
let promise = new Promise((resolve, reject) => {
    console.log("Comando de dentro da promise")
});
console.log(promise)
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8u8uyttz42xcd6z3qrx.png) 
 
Perceba que por ela não ter sido resolvida ainda, ela apresenta o status de *pending*.

### Resolvendo uma promise

```javascript
promise = new Promise((resolve, reject) => {
    resolve(10)
});
console.log(promise)
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y33z6416gkkoqcdpujw.png) 
 
Agora passando o valor 10 para a função *resolve* teremos a promise com o status de *fulfilled* e valor 10.

### Rejeitando uma promise

```javascript
promise = new Promise((resolve, reject) => {
    reject("Erro na promise")
})
console.log(promise)
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fyn7l8in0cukwksi1dlo.png) 
 
Note que a promise é rejeitada possuindo um motivo pelo qual ela foi rejeitada, neste caso é o texto passado para a função *reject*.

### Trabalhando com promises na prática
Na prática usamos promises para retorno de uma chamada de API, uma escrita ou leitura de arquivo assíncrona, uma consulta ao banco de dados utilizando JavaScript, enfim, são N situações, mas todas envolvem um retorno que é assíncrono.

Vamos utilizar a API do [JSON Placeholder](http://jsonplaceholder.typicode.com/) para buscarmos dados de forma assíncrona.

```javascript
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then(response => response.json())
  .then(user => console.log(user))
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/suj2chayjdefyzl7zf4d.png)
É utilizado aqui a função *fetch* (nativa do JavaScript) para fazer a chamada para a API de usuários, o retorno dela é uma **promise** que ao ser resolvida (quando a chamada assíncrona terminar a execução) chamará a primeira instrução  *then* que tem como função transformar a resposta em JSON, e passar o resultado como retorno para o próximo bloco *then*. 
Sendo assim na segunda instrução *then* teremos o JSON com os dados de usuário sendo passados como parâmetro para ser utilizado dentro desta função, neste caso os dados são exibidos no console.

#### Tratando erros na Promise

```javascript
fetch('https://jsonplaceholder.typicode.com/users/1')
  .then(response => response.json())
  .then(user => {
  	if(user.id == 2)
    	console.log(user)
    else
    	throw new Error("Não é o usuário de ID 2") 
  }).catch((error) => console.log(error.message))
```
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mvm49t6jahtejt5lib9q.png)
Aqui fazemos a mesma chamada feita anteriormente buscando pelo usuário de `id = 1`, então dentro do bloco *then* é feita uma verificação em que caso o id seja 2 são exibidos os dados do usuário, caso contrário é lançada uma **exceção**, e esta é tratada no bloco *catch*, em que neste exemplo será exibida no console, mas em uma aplicação real geralmente seria neste ponto que ela seria enviada para o arquivo de log do sistema, ou apresentado algum tipo de mensagem para o usuário comunicando sobre o erro.

### Considerações finais
Note que nesta forma de uso das promises temos a possibilidade de aninhar várias funções de *callback* para uma mesma promise, isso ajuda muito na questão de organização do código, pois de acordo com a arquitetura utilizada pode-se aplicar diferentes regras de negócio em cada bloco *then*.
Mas existe uma outra forma de tratar as promises que são utilizando os comandos *async/await* o qual falaremos em um próximo post.

_Obrigado_ por ter lido até aqui, qualquer dúvida ou sugestão deixa aqui nos comentários. **Um forte abraço!**