Imagine que você precisa que um amigo seu realize uma tarefa para você. Exemplo: Ir até o correio e postar uma carta, mas você não sabe se quando seu amigo chegar lá, o correio estará aberto ou fechado.

Então, você precisa passar uma instrução para seu amigo. Se o correio estiver aberto, poste a carta por favor, caso contrário, me ligue avisando que não conseguiu postar.

Procurando cartas

O que farei com essas cartas?

Isso poderia ser um exemplo de estrutura condicional em JavaScript, certo? Porém, há uma diferença: Você não saberá o que vai acontecer, a tarefa pode ocorrer depois de algum tempo que você pediu, e seu amigo terá que fazer uma promessa a você sobre o que fazer com o resultado.

Neste post, falarei sobre Promise.

Este conceito vem solucionar problemas que são assíncronos com relação a execução do seu código. Ou seja, o resultado de um processamento não acontece na mesma hora que você chamou sua execução, e ele exige um tratamento de sucesso ou falha.

Vamos ao código

O código seguinte faz uma requisição assíncrona a uma API do github, pra pegar os dados de um usuário qualquer.

Das linhas 7 a 16, temos a definição de uma função, que se chama getUserFromGithub. Ela faz uma requisição pra API do github, recebendo o username do usuario como argumento.

Na linha 18 pegamos o resultado da requisição, e na linha 19 exibimos a resposta dentro de um alert.

E voilá!!!

Erro assíncrono

Ué...

Parece que algo deu errado... O que acontece é que o JS é mais rápido que o tempo da requisição. Na linha 18, a requsição é feita, mas o JS não espera pela resposta da API, então a função entrega apenas um undefined para a variável. Na linha 19, o JS exibe o undefined recebido na linha de cima dentro do alert.

Será que esse caso encaixa com nossa definição de promise?

  • Requisição assíncrona? Check
  • Tratamento de resposta com sucesso ou falha? Check

Adaptando o código para Promise

Adaptando a promise no código anterior, ficaria assim:

Executando o código acima no navegador...

Erro assíncrono

Deu certo!!!

Na linha 8 foi adicionado um retorno de uma instância de um objeto do tipo Promise. Na hora de instanciar, ela recebe uma função com dois argumentos, resolve e reject.

Dentro da Promise, você passa qualquer trecho de código que seja assíncrono. Se você quer que um determinado resultado seja retornado como sucesso, ele deve ser passado dentro da função resolve. Se você quer que um determinado resultado de falha seja retornado, ele deve ser passado dentro da função reject, como foi feito em resolve(JSON.parse(this.responseText)); e em reject({error: 'Requisição falhou'});.

O modo como a função com trecho assincrono é chamada também é modificada. Lembra que agora a função getUserFromGithub retorna um objeto do tipo Promise?

Então, esse objeto possui alguns métodos específicos, como o then e o catch. O que é passado como função dentro do then é executado quando a ação assíncrona é feita com sucesso (no exemplo inicial, quando o correio está aberto). O argumento response é equivalente ao que foi passado dentro do resolve na função assíncrona

Já o que é passado dentro do catch é executado quando o código assíncrono falha (quando o correio está fechado, no exemplo inicial). O argumento errorMessage é equivalente ao que foi passado dentro do reject na função assíncrona.

E o caso de falha? Como posso testar?

Bom, você pode experimentar trocar a URL da API por uma URL que não existe. Pode trocar de repente `https://api.github.com/users/${userName}` por `https://api.githu.com/users/${userName}`. Repare que eu comi um b na URL. Veja que no alert, passará a ser exibido a mensagem que foi definida em caso de falha, no reject.

O que acha de trocar suas chamadas a APIs por promises?