Promises JavaScript

Neil Prado
Jaguaribe Tech
Published in
5 min readJan 24, 2018

Promise, ou Promessa, é um objeto usado para processamento assíncrono. Uma Promise representa um valor que pode estar disponível agora, no futuro ou nunca.

Por que isso é importante? Imagine um site que carrega dados de uma API, então quando o dados é recebido é possível processá-lo e formatá-lo de forma que fique agradável visualmente para o usuário final. Se tentarmos fazer o processamento e a formatação dos dados da API antes de realizar a coleta dos dados, o resultado será um erro, ou uma página em branco. Usando uma Promise, é assegurado que a API não será processada nem formatada até que a chamada da API seja bem sucedida.

Sintaxe

A sintaxe básica de uma promessa no Javascript pode ser ilustrada pelo seguinte código:

Nesse caso, o executor seria a função que recebe dois argumentos resolve e reject, e é executada imediatamente pela implementação da Promise, passando seus argumentos. As funções passadas como argumento da Promise, quando chamadas, resolvem em caso de sucesso, ou rejeitam em caso de falha. Então, o executor começa o trabalho assíncrono que deverá chamar um dos argumentos para definir assim o estado da promessa.

Um Promise está em um dos estados, conforme a figura abaixo exemplifica:

  • pending: Estado inicial (pendente), ainda não foi realizada, nem rejeitada.
  • fulfilled: Houve sucesso na operação, a Promise está realizada.
  • rejected: Houve rejeição na operação da Promise.
  • settled: A Promise foi realizada ou rejeitada.

Métodos

Os métodos são parte intrínseca do construtor da Promise, além da propriedade length (não citada, cujo valor é 1), as Promises têm as seguintes propriedades:

  • Promise.all(iterable) - Retorna uma Promise que é executada quando todas as Promises do argumento forem executadas com sucesso, ou rejeita assim que uma das Promises do argumento iterado for rejeitada. Se retornar a Promisse com sucesso, é executado um array de valores das Promises executadas de forma bem sucedida na mesma ordem definida na iteração. Se for rejeitada, será com a razão da primeira Promise iterável que rejeitou. Esse método é interessantíssimo caso seja utilizado como resultado agregado de múltiplas Promises.
  • Promise.race(iterable) - Retorna uma Promise que executa ou rejeita assim que uma das Promises iteráveis são executadas ou rejeitadas e retorna o valor, ou a mensagem daquela Promise.
  • Promise.reject(reason) - Retorna um objeto Promise que é rejeitado e exibe uma ação de erro.
  • Promise.resolve(value) - Retorna um objeto Promise que é executado. Se o valor, for usado o .then, então a Promise irá seguir o que foi definido pelo .then, adotando seu estado eventual, caso contrário a Promise será executada com o valor.

As Promises sob uma ótica simples

À primeira vista parece algo bastante complicado de entender. De fato Promises é meio confuso no início então vou procurar ajudar com um exemplo mais lúdico.

Imagine que você é uma criança. Seus pais irão te dar um console caso suas notas na escola sejam boas. De fato você não sabe se vai receber, isso vai depender do seu desempenho na escola.

Trazendo para o universo JavaScript:

Nesse exemplo temos uma variável booleana niceGrades, para definir se as notas foram boas ou não.

Em seguida, newConsole representa uma promessa que pode ser bem sucedida e a criança recebe um Nintendo Switch novinho, ou rejeitada por suas notas serem ruins.

Agora que a Promise foi criada, vamos consumi-la:

Foi criada uma função chamada showGrades e o intuito dessa função é consumir a Promise newConsole. Depois é preciso definir ações para mostrar o que fazer se for bem sucedido ou rejeitado.

Para o caso de ser bem sucedido é usado o .then é utilizado, caso seja rejeitado, então o .catch será usado para mostrar o valor.

Nesse exemplo utilizado, temos: .then(fulfilled {…}). Mas qual o valor do fulfilled? Como mencionado acima, o fulfilled significa que houve sucesso resolve(valor_do_sucesso), então nesse exemplo irá retornar o console. Caso o resultado seja um erro, temos o: .catch(error {…}), cujo valor é o reject(valor_do_erro) citado na Promise, que nesse exemplo é a negativa de receber o novo console.

Suponhamos que você é a criança e, sabendo que os Joy-Cons são destacáveis e que é possível que duas pessoas joguem, sua ideia é chamar seu amigo para jogar contigo, então pode-se fazer uma Promise e encadeá-la.

Agora, atualizar a função showGrades com a segunda Promise de forma encadeada.

Deve-se notar que na segunda Promise, a playWithMe, o reject fora omitido e o resolve fora encurtado. E assim que as Promises são encadeadas.

Ao iniciar esse artigo, disse que as Promises eram assíncronas, mas o que de fato isso quer dizer? Vamos usar esse exemplo para explicar o que seria essa assincronicidade:

Qual seria a sequência de mensagens esperada? Provavelmente seria:

1-“Before show the grades”
2- “Dear friend, come to play with me in my Nintendo Switch” (em caso verdadeiro)
3- “After show the grades”

Porém, a saída é:

1-“Before show the grades”
2- “After show the grades”
3- “Dear friend, come to play with me in my Nintendo Switch” (em caso verdadeiro)

A justificativa é que a assincronicidade da Promise não inviabilizará o código de rodar por haver um resultado a ser esperado pela Promise. Tudo que for preciso para esperar por uma Promise para prosseguir, pode ser colocado em um .then.

Promises na ES7

A versão ES7 trará uma sintaxe ainda mais elegante. Introduzindo as palavras reservadas async e await, fazendo com que o código fique mais legível e simples de entender, sem o .then e o .catch.

Escrevamos nosso exemplo na sintaxe do ES7:

Toda vez que for necessário retornar a Promise em uma função, usa-se async naquela função. Como usado no exemplo: async function playWithMe(console).

Sempre que precisar fazer a chamada de uma Promise, proceda com await. Como expressa o exemplo: let myConsole = await newConsole.

Use o try{…} catch(error){…} para capturar o erro na Promise, ou seja, a Promise rejeitada.

Leitura complementar

Há um material muito vasto na internet sobre Promises, o MDN disponibiliza a documentação oficial, também há um material interessantíssimo no BrasilJS, o PromiseJS traz um belo artigo e também no Medium, Eric Elliott dá ainda mais base para o entendimento das Promises.
Mattias Petter Johansson do canal Fun Fun Function fala sobre Promises aqui e async/await neste vídeo

Considerações finais

Promises se tornaram parte integrante do JavaScript, incluindo o fetch que é amplamente utilizado atualmente e as funções assíncronas acabam se comportando à primeira vista, em funções síncronas. As Promises providenciam uma forma mais legível do callback e, o ES7 promete deixar as Promises ainda menos complexa com a chegada do async/await.

--

--