Pablo Danilo
6/11/2020 Pablo Danilo

Promise

blog-feature-image

Pending…

Fala galera, nada melhor pra começar um post de promise do que um status pendente. E vamos ver se o retorno vai ser resolvido ou rejeitado! haaa 😜🤙

No último dia 06 criei uma talk na firma, desenvolvida com o intuito de entender o que é essa tal de promise de forma simples e rápida, então bora lá.

Para começar é necessário entendermos alguns conceitos básicos, mas nada relacionado à programação no momento.

O que é uma promessa?

Promise = Promessa

É entendido como a firmação de um compromisso feito à uma outra parte, registrando a intenção de cumprir com o que foi prometido.

um exemplo de promessa, é você me prometer que vai ler até o final? hahaha 😅

Prometeu?

Ah, beleza, então podemos continuar…

O que é comunicação síncrona e assíncrona?

Mas que bicho é esse? 🤯 🤔
…calma, calma, o conceito é bem simples, e entendendo isso, quando entrarmos nos exemplos práticos na programação, você vai tirar o assunto de letra.

  • comunicação síncrona?
    É quando temos a oportunidade de falar com alguma pessoa de maneira direta. Ou seja, o emissor passa a mensagem e o receptor responde, sendo que o diálogo ocorre naquele momento.

  • comunicação assíncrona?
    É a que está desconectada do tempo e do espaço. Ou seja, o comunicador e o receptor podem manter relacionamento na medida em que tenham tempo disponível.
    Por exemplo uma conversa no whatsapp… o comunicador envia uma mensagem e o receptor responde no outro dia. 🤬
    Por favor, não repitam essa façanha em casa!

Legaaaal, aprendeu algo novo?
E nem era tão complicado assim 😬


Bora aplicar esses conhecimentos na programação?

Uma promise representa um proxy para um valor que não é necessariamente conhecido quando a promessa é criada.

** proxy: é o termo utilizado para definir os intermediários entre o usuário e seu servidor.

Então, resumindo, uma promise é o intermediário entre uma ação e sua resposta.

iihh, bugou? 👾

Logo você vai entender, antes disso vamos entender os estados de uma promise.

estados (Estados da promise.)

Acredito que pra ficar ainda mais claro o que vou explicar daqui pra frente, é importante você saber o fluxo que uma promise segue:

fluxo (Fluxo da promise.)

Então, agooooora sim!!!

Quando um estados ocorre, existem os métodos para o tratamento das ações seguintes.
Então, o primeiro método a ser chamado é o then da promise (caso você queira tratar o rejected, você pode dividir a responsabilidade e chamar o catch), dentro dele podemos chamar os métodos de tratamento associados ao estado, que seriam o resolved ou o rejected.
E temos dois métodos um pouco diferentes, que são o Promise.all e o Promise.race

Esses dois métodos, transformam uma lista de promises em uma única promise,

  • Promise.all: Este método aguarda todas as promises serem resolvidas, ou no caso de uma ser rejeitada, o retorno é o rejected.

  • 🏃🏼‍♀️ Promise.race: O método race requer que ao menos uma promise seja resolvida, a qual é a vencedora da “corrida”, sendo ela resolved ou rejected.

Depois de uma promise ser resolvida, ou rejeitada, poderíamos usar os prototypes de Promise, then e catch, que podem ser encadeados, criando uma operação chamada composição.

Viu, aprendemos mais algumas coisas interessantes hoje né?!
Pra ficar ainda mais claro, vamos para alguns exemplos práticos.


Então, o nosso problema à ser resolvido é montar um cubo mágico.
Você sabe como resolver? (caso não saiba: fica a dica => https://cubovelocidade.com.br) 👻

fluxo (Cubo mágico.)

O primeiro passo é montar uma função que vai ter como retorno uma promise.

const montarCuboMagico = pessoa => {
  return new Promise((resolve, reject) => {
    /**
     * Pessoas que conseguem ou não montar.
     */
    const resolucoes = {
      joao: true,
      maria: true,
      miguelito: false
    }

    /**
     * Verificando se o nome passado como parâmetro consegue ou não resolver.
     */
    const resposta = resolucoes[pessoa]

    /**
     * Resposta da promise.
     * Se a resposta for true, retorna resolve, caso contrário, retorna false.
     */
    return resposta ? resolve() : reject()
  })
}

Então, agora podemos chamar a função dentro do escopo da função post(), e tratar o seu retorno.

const post = () => {
  /**
   * Função para montar o cubo, passando o nome da pessoa.
   */
  montarCuboMagico('maria')
    .then(() => console.log('Conseguiu montar'))
    .catch(() => console.log('Não conseguiu montar'))

  montarCuboMagico('miguelito')
    .then(() => console.log('Conseguiu montar'))
    .catch(() => console.log('Não conseguiu montar'))
}

/**
 * Chamando a função post.
 */
post()

O retorno das chamadas dessas funções em ordem seriam:

/**
 * resposta para Maria
 */
'Conseguiu montar'

/**
 * resposta para José
 */
'Não conseguiu montar'

Nestes exemplos fica clara a ordem das chamadas das funções e seus respectivos tratamentos encadeados com os prototypes de Promise then e catch.

Porém, atualmente aqui na firma, procuramos resolver encadeamentos de funções de uma outra forma beeeem mais legal!!
Maaaas, calma aí jovem Padawan, ainda falta vermos o Promise.all e o Promise.race.

Bora para os próximos exemplos, pra começar, o Promise.all:

/**
 * Array de pessoas para tentar montar o cubo.
 */
const pessoasParaResolverOCubo = ['joao', 'maria']

/**
 * Loop para percorrer todos os nomes do array.
 */
const promessa = pessoasParaResolverOCubo.map(montarCuboMagico)

Promise.all(promessa)
  .then(() => console.log('Resolvido'))
  .catch(() => console.log('Não resolvido'))

  /**
   * Retorno das chamadas da função montarCuboMagico.
   */
  joao = 'resolved'
  maria = 'resolved'

  /**
   * Retorno do Promise.all.
   */
  'Resolvido'
]

Então, nosso Promise.all retornou “Resolvido”, pois o resultado das duas chamadas da função foram resolved, se por acaso uma das duas chamadas tivesse retornado rejected o resultado do nosso Promise.all seria automaticamente “Não resolvido”."

Agora partiu pra explicação do Promise.race:

/**
 * Array de pessoas para tentar montar o cubo.
 */
const pessoasParaResolverOCubo = ['miguelito', 'maria']

/**
 * Loop para percorrer todos os nomes do array.
 */
const promessa = pessoasParaResolverOCubo.map(montarCuboMagico)

Promise.Race(promessa)
  .then(() => console.log('Resolvido'))
  .catch(() => console.log('Não resolvido'))

  /**
   * Retorno das chamadas da função montarCuboMagico.
   */
  miguelito = 'rejected'

  /**
   * Retorno do Promise.all.
   */
  'Não resolvido'
]

Então, nosso Promise.race retornou “Não resolvido”, pois o resultado da primeira chamada da função foi rejected, Entendesse que ela foi a primeira função a ter um retorno, e assim ganhou a nossa “corrida”. Se por acaso a outra chamada tivesse retornado resolved mais rápido o resultado do nosso Promise.race automaticamente seria “Resolvido”."

Chegou a hora galeraaaa!!

…De eu apresentar dois carinhas muito legais pra vocês…
Eles são conhecidos como async e await, e eles resolvem aquele problema de encadeamento de código que comentei ali em cima.
E antes de mostrar o que eles fazem na prática, vamos para uma breve explicação sobre eles.

  • async:
    Ele transforma a função atual em uma função assíncrona, retornando uma promise.

  • await:
    Esse método só pode ser chamado se estiver dentro de uma função assíncrona. E seu papel é fazer com que a função espere a resposta da promise para que o código possa continuar a sua execução.

Agoooora sim, vamos aplicar esse conhecimento na prática.

O exemplo aqui, é transformar aquela primeira função post() em assíncrona e fazer com que ela espere os resultados das chamadas da função montarCuboMagico().

const post = async () => {
  /**
   * Função para montar o cubo, passando o nome da pessoa.
   */
  try {
    await montarCuboMagico('maria')

    await montarCuboMagico('miguelito')
  } catch (error) {
    console.log(error)
  }
}

Aqui transformamos a função post em assíncrona, colocando o nosso amigo async no começo da função, fazendo com que ela retorne automaticamente uma promise, após, para a função aguardar as chamadas da função montarCuboMagico adicionamos o outro colega await. E colocamos as chamadas dentro de um bloco try/catch, para podermos tratar o sucesso ou a falha das nossas promises.


Considerações finais

O conhecimento sobre promises hoje em dia, é fundamental, e acredito que não existe mais como programar sem ele. Combinando as promises com os nossos amigos async/await, resolvemos muitos side effects.

Portanto, espero que esse post tenha te ajudado na sua caminhada como dev, e você tenha entendido de forma simples e rápida como usar essa tal de promise. hihi 😁

Vou deixar aqui os slides da minha talk, caso queira dar uma olhadinha, foi muito legaal montar esse conteúdo.


“Programadores e artistas são os únicos profissionais que tem como hobby a própria profissão.”

Pablo Danilo 👾

NOS ACOMPANHE NAS REDES SOCIAIS