Entendendo Promises
Tags: javascript, promises, programming, tutorial
Published: 2022-03-13 17:03:30

#PROMISES

Antes de entendermos as `Promises`, temos de conhecer as diferenças entre comportamentos `síncronos` e `assíncronos`.

##Síncrono e Assíncrono

Como o próprio nome pode nos ajudar a deduzir, **síncrono** acontece em sincronia, ou seja, que ocorre em mesmo tempo que outra coisa. Já **assíncrono** é o oposto, é algo que não acontece junto com outra coisa. Podemos exemplificar esses comportamentos síncronos e assíncronos, como uma chamada de telefone e envio de e-mail, respectivamente.

Sabendo o básico, podemos afirmar que o **Javascript** é **síncrono**, sendo executado linearmente de cima para baixo. Isso se deve ao fato que ela é uma linguagem `Single Thread`, então cada linha de comando só será executada quando a anterior é finalizada. 


```javascript
console.log('Primeira linha');
console.log('Segunda linha');
console.log('Terceira linha');
console.log('Quarta linha');
console.log('Quinta linha');
```


Sendo assim, o código acima quando executado, nos retorna:


```javascript
Primeira linha
Segunda linha
Terceira linha
Quarta linha
Quinta linha
```


No Javascript temos a função assíncrona `setTimeout()`, onde no primeiro parâmetro ela espera uma função e no segundo o tempo que após ser feita a chamada da função, ela será executada, isso em milissegundos.

Sendo assim, vamos analisar o código abaixo: 


```javascript
console.log('Primeira linha');
console.log('Segunda linha');

setTimeout(() => {
  console.log('setTimeout');
}, 2000);

console.log('Terceira linha');
console.log('Quarta linha');
console.log('Quinta linha');
```


Caso a função `setTimeout()` fosse _síncrona_, deveriamos ter o retorno abaixo, já que está sendo chamado na terceira linha:


```
Primeira linha
Segunda linha
setTimeout
Terceira linha
Quarta linha
Quinta linha
```


Porém, ela é uma função que não acontece junto com outra coisa -_assíncrona_ - ela só sera retornada com uma condição ou parâmetro, que no caso, é ser executada após 2 segundos, nos retornando: 


```
Primeira linha
Segunda linha
Terceira linha
Quarta linha
Quinta linha
setTimeout
```


Ou seja, ela executa todas as outras linhas de maneira _síncrona_, quando chega no `setTimeout()`, ela é entregue para uma request **separada** que é executada fora da thread do Javascript _- lembrando que o código que escrevemos é executado em uma única thread -_ fazendo com que o restante continue a ser executado.

Agora já com o conhecimento de **síncrono/assíncrono**, podemos tratar das `Promises`. Como o próprio nome diz, é uma promessa que pode ou não estar disponível em algum momento, sendo assim, ela possui um comportamento **assíncrono**.

Promise é um objeto que possui três possíveis estados, sendo eles:

- **Pending** – Estado inicial, pendente de execução
- **Fulfilled** – Concluido com sucesso
- **Rejected** – Ocorreu algum erro

A mesma recebe **dois parâmetros**, sendo eles comumente chamados de `resolve e reject`, sendo assim, apenas um dos métodos de tratamento será chamado. Para acessar a resposta dessa promisse, temos o `.then` e o `.catch`, sendo responsáveis por tratar a resposta e o erro respectivamente.

O método `.then` irá registrar um _callback _de **sucesso** e é comum executar duas ou mais operações assíncronas consecutivas, executando a ação posterior apenas quando a anterior for bem sucedida, isso é possível realizando o encadeamento do método `.then`, onde o mesmo retorna uma nova promise diferente da original.

```javascript
 new Promise((resolve, reject) => {
  console.log('Inicio da Promise');
  const numero = 10;

  resolve(numero);
})
  .then((value) => {
    console.log(`Primeiro valor: ${value}`);
    return value;
  })
  .then((newValue) => {
    console.log(`Valor somado de 5: ${newValue + 5}`);
  });
```

No código foi chamado a função construtora passando os dois parâmetros como argumento e a chamada de uma função callback.
Logo de  início já é executado nosso primeiro `console.log` e o armazenamento de _numero_ em uma constante, recebendo o valor 10, logo após chamamos nosso `resolve(numero)`, passando como resolvida nossa promise e ela recebe esse número.

Agora devemos tratar esse resultado fazendo a chamada do nosso primeiro `.then` onde o mesmo recebe um parâmetro `value`, esse valor recebe o que foi passado em resolve, logo `value ` equivale a `numero`, sendo assim, chamamos o `console.log` desse `value` e retornamos ele para que possamos utilizar no próximo encadeamento de `.then`, onde iremos tratar o retorno anterior.
Para diferenciarmos, foi passado como parâmetro agora `newValue` onde o mesmo recebeu o valor anterior e será tratado no console, sendo acrescido de 5.

O resultado final desse código:

```javascript
new Promise((resolve, reject) => {
  console.log('Inicio da Promise');
  const numero = 10;

  resolve(numero);
})
  .then((value) => {
    console.log(`Primeiro valor: ${value}`);
    return value;
  })
  .then((newValue) => {
    console.log(`Valor somado de 5: ${newValue + 5}`);
  });
```

Agora iremos tratar a promise caso fosse chamado o `reject`:

```javascript
new Promise((resolve, reject) => {
  console.log('Inicio da Promise');
  const numero = 10;

  reject('Número não identificado');
})
  .then((value) => {
    console.log(`Primeiro valor: ${value}`);
    return value;
  })
  .then((newValue) => {
    console.log(`Valor somado de 5: ${newValue + 5}`);
  })
  .catch((error) => {
    console.log(`Houve um erro: ${error}`);
  });
```

Como fazemos a chamada de `reject()`, a função logo irá chamar o método `.catch` que também recebe um parâmetro e o mesmo é retornado no `console.log()`, renderizando:

```
Inicio da Promise
Houve um erro: Número não identificado
```

Um método muito utilizado, é a API fetch que realiza requisições HTTP através de Promises.