← Home

Promises em JavaScript: entendendo o básico

PROMISES Antes de entendermos as Promises, temos de conhecer as diferenças entre...

#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.

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:

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:

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.

 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:

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:

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.