Artigo original escrito por: Cem Eygi
Artigo original: JavaScript Promise Tutorial: Resolve, Reject, and Chaining in JS and ES6
Traduzido e adaptado por: Daniel Rosa

As promises são uma das maneiras pelas quais podemos lidar com operações assíncronas em JavaScript. Muitas pessoas têm dificuldade em entender o funcionamento das promises. Por isso, neste artigo, tentarei explicá-las da maneira mais simplificada que eu puder.

As promises são um tópico bastante amplo. Por isso, não quero entrar em todos os detalhes aqui. Você, contudo, poderá encontrar aqui uma introdução geral sobre o que são as promises, explicações sobre termos como resolve, reject e encadeamento, assim como um exemplo de código para a criação e o uso de promises.

Pré-requisito: para entender melhor este artigo, confira meu outro artigo sobre callbacks em JavaScript.

O que é uma promise?

Uma promise em JavaScript é semelhante a uma "promessa" na vida real. Quando fazemos uma promessa na vida real, ela é uma garantia de que faremos algo no futuro. Isso ocorre porque promessas podem apenas realizar coisas no futuro.

Uma promessa pode ter 2 resultados possíveis: ela será cumprida quando chegar a hora ou não.

Isso também vale para as promises do JavaScript. Quando definimos uma promise em JavaScript, ela será resolvida (em inglês, resolved) quando chegar a hora, ou rejeitada (em inglês, rejected).

Promises em JavaScript

Em primeiro lugar, uma promise é um objeto. Há 3 estados possíveis para o objeto Promise:

  • Pending: é o estado inicial (em português, pendente), antes da Promise ter ou não ter sucesso
  • Resolved: promise concluída com sucesso
  • Rejected: promise que falhou
Ekran-Resmi-2020-06-06-12.21.27
Representação do processo das promises

Por exemplo, quando solicitamos dados do servidor usando uma Promise, ela estará em modo pending (pendente) até recebermos nossos dados.

Se conseguirmos obter as informações do servidor, a Promise será resolvida (em inglês, resolved) com sucesso. Se não obtivermos as informações, no entanto, a Promise estará em estado rejected (em português, rejeitada).

Além disso, se houver diversas solicitações, após a primeira Promise ser resolvida (ou rejeitada), um novo processo iniciará no qual podemos associá-las diretamente usando um método chamado encadeamento.

Se preferir, você pode assistir a versão em vídeo do conteúdo deste artigo abaixo:

Qual é a diferença entre as callbacks e as promises?

A diferença principal entre as funções de callback e as promises é o fato de podermos associar uma callback a uma promise em vez de passá-la. Assim, seguimos usando funções de callback com promises, mas de um modo diferente (encadeamento).

Essa é uma das grandes vantagens de se usar Promises, mas qual o motivo para isso?

O que é o encadeamento?

As funções de callback já foram usadas sozinhas para operações assíncronas em JavaScript por muitos anos. Em alguns casos, no entanto, usar promises pode ser uma opção melhor.

Se houver várias operações assíncronas a serem feitas e se tentarmos usar as boas e velhas callbacks com elas, acabaremos entrando em uma situação a que chamamos de callback hell (ou o inferno das callbacks, em português):

firstRequest(function(response) {  
    secondRequest(response, function(nextResponse) {    
        thirdRequest(nextResponse, function(finalResponse) {     
            console.log('Final response: ' + finalResponse);    
        }, failureCallback);  
    }, failureCallback);
}, failureCallback);

No entanto, se tratarmos das mesmas operações com promises, como podemos anexar callbacks em vez de passá-las, o mesmo código que vemos acima parecerá agora bem mais limpo e fácil de ler:

firstRequest()
  .then(function(response) {
    return secondRequest(response);
}).then(function(nextResponse) {  
    return thirdRequest(nextResponse);
}).then(function(finalResponse) {  
    console.log('Final response: ' + finalResponse);
}).catch(failureCallback);

O código acima mostra como várias callbacks podem ser encadeadas, uma após a outra. O encadeamento é um dos melhores recursos das promises.

Como criar e usar uma promise passo a passo

Primeiro, usaremos um construtor para criar um objeto Promise:

const myPromise = new Promise();

Ele recebe dois parâmetros: um para o sucesso (resolve) e um em caso de erro (reject):

const myPromise = new Promise((resolve, reject) => {  
    // Condição
});

Por fim, temos a condição. Se ela for atendida, a promise será resolvida. Do contrário, ela será rejeitada:

const myPromise = new Promise((resolve, reject) => {  
    let condition;  
    
    if(condition for atendida) {    
        resolve('A promise foi resolvida com sucesso.');  
    } else {    
        reject('A promise foi rejeitada.');  
    }
});

Desse modo, criamos nossa primeira promise. Agora, vamos usá-la.

then( ) para promises resolvidas:

Se você der uma olhada novamente na imagem do início da publicação, verá que temos 2 casos: um para promises "resolved" e outro para promises "rejected". Se a promise for resolvida (em caso de sucesso), algo acontecerá a seguir (dependendo do que fazemos com a promise de sucesso).

myPromise.then();

O método then( ) é chamado após a promise ser resolvida. Em seguida, podemos decidir o que fazer com ela.

Por exemplo, vamos colocar no console a mensagem que recebemos da promise com console.log():

myPromise.then((message) => {  
    console.log(message);
});

catch( ) para promises rejeitadas:

No entanto, o método then( ) serve apenas para as promises resolvidas. E se a promise não for resolvida? Neste caso, precisaremos usar o método catch( ) .

Da mesma forma como anexamos o método then( ), podemos, também, anexar diretamente o método catch( ) logo após o then( ):

myPromise.then((message) => { 
    console.log(message);
}).catch((message) => { 
    console.log(message);
});

Assim, se a promise for rejeitada, ela saltará para o método catch( ) e, dessa vez, veremos uma mensagem diferente no console.

Em resumo

É assim que criamos uma promise em JavaScript e a utilizamos em casos onde ela foi resolvida ou rejeitada. As promises são um assunto muito mais amplo, podendo haver muito mais para se aprender com elas. Entender como elas funcionam é algo que leva tempo.

Este artigo é apenas uma introdução às promises. Espero que você o tenha achado útil para ter uma ideia sobre o que as promises em JavaScript são e sobre como utilizá-las.

Se quiser aprender mais sobre o desenvolvimento para a web, fique à vontade para visitar o canal do YouTube do autor para saber mais.

Obrigado pela leitura!