JavaScript Promise

JavaScript Promise: do que se trata?

O Promise é uma funcionalidade nativa do JavaScript 6 (ECMA 2015) para tratar requisições assíncronas e/ou demoradas.

Quando precisamos realizar chamadas que podem resultar nos dados esperados ou erros, normalmente utilizamos eventos ou callbacks.

Por exemplo,


let imagem_principal = document.querySelector('.img_principal');

imagem_principal.addEventListener('load', function() {
  // faz alguma coisa quando a imagem principal é carregada
});

imagem_principal.addEventListener('error', function() {
  // realiza algo quando acontece algum erro ocorre
});

No exemplo acima é possível que algum evento ocorra antes de criarmos os listeners da imagem.
Para contornar isso, podemos utilizar a propriedade “complete” da imagem para sabermos que ela foi carregada:


let imagem_principal = document.querySelector('.img_principal');

function carregada(){
  // faz alguma coisa quando a imagem principal é carregada
}

if(imagem_principal.complete){
  carregada();
} else {
  imagem_principal.addEventListener('load', carregada);
}

imagem_principal.addEventListener('error', function() {
  // realiza algo quando acontece algum erro ocorre
});

Porém essa aproximação também não captura erros de carregamento da imagem antes de criarmos o listener. Isso pode ser mais complicado ainda se precisarmos saber se um conjunto de imagens foram carregadas corretamente e se alguma exibiu erro.

Eventos não são o melhor caminho

Eventos são muito bons quando algo pode acontecer várias vezes no mesmo objeto tipo keypress, mousever etc. Nesses eventos não precisamos nos importar com o que aconteceu com o objeto antes de anexarmos o listener. Mas quando precisamos de acesso assíncrono com possibilidade de sucesso/erro, precisaríamos algo do tipo:


imagem1.executeIstoSeOuQuandoCarregado(function(){
  // imagem carregada
}).seErroChamaIsto(function(){
  // erro
});

// ...

quandoCarregarTodasImagens([imagem1, imagem2, imagem3]).executeIssso(function(){
  // todas as imagens carregadas
}).seAlgumaFalhouExecuteIsso(function(){
  // alguma falhou
});

Isto é exatamente o que uma Promise faz mas com os nomes dos métodos mais padronizados que esses.
Se o elemento imagem do HTML possuísse o método “ready” que retornasse um Promise poderíamos fazer da seguinte forma:


imagem1.ready().then(function(){
  // carregada
}, function(){
  // erro
});

// ...
Promise.all([imagem1.ready(), imagem2.ready(), imagem3.ready()]).then(function(){
  // todas imagens carregadas
}, function(){
  // alguma deu erro
});

Estados de um Promise

Uma Promise possui alguns estados mutualmente exclusivos:
pendente: estado inicial, ainda não concluído ou rejeitado.
realizada: sucesso na operação
rejeitado: falha na operação.
determinado: a Promise ou está realizada ou rejeitada, mas não pendente.

Utilizando uma Promise

Para utilizarmos uma Promise, temos que defini-la e chama-la posteriormente:


let promise = new Promise(function(resolve, reject) {
  // fazer algo assíncrono...

  if (/* retorno positivo */) {
    resolve("Funcionou!");
  } else {
    reject(Error("melou..."));
  }
}); 

O construtor da Promise tem apenas um argumento, um callback com dois parâmetros, um quando executa corretamente “resolve” e outro quando ocorre algum erro “reject”. Ao fazer algo assíncrono com um callback dentro da Promise, se deu certo, chamamos o “resolve” caso contrário “reject”.
É como o “throw” no JavaScript, é utilizado mas não é obrigatório rejeitar com um objeto Error. Mas o bom de se utilizar o objeto Error é que ele captura o trace do erro facilitando assim o debug.

A Promise acima foi definida e abaixo seria sua utilização:


promise.then(function(result) {
  console.log(result); // exibe: "Funcionou!"
}, function(err) {
  console.log(err); // exibe: Error: "melou..."
});

Mais informmações

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise

https://spring.io/understanding/javascript-promises

http://www.mattgreer.org/articles/promises-in-wicked-detail/

Se houver alguma dúvida, sugestão ou percebeu algum erro de digitação, não hesite em entrar em contato que responderei tão rápido quanto puder e atribuirei o crédito pela ajuda.

Até mais!
André Fellows

Leave a Reply Cancel reply