Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Stacks de .then()

Estou com uma dúvida sobre os callbacks do 'then'. Na linha comentada do trecho abaixo, retirado do vídeo, qual é o 'resolve' que retorna aquele .then()?

ConnectionFactory
      .getConnection()
      .then(connection => new NegociacaoDao(connection))
      .then(dao => dao.listaTodos()) //de onde veio este .then?
      .then(negociacoes => {
        negociacoes.forEach(negociacao => {
          this._listaNegociacoes.adiciona(negociacao)
        })
      })

Pelo que eu entendi, o próprio retorno do .then() seria um resolve para um próximo .then() da mesma Promise. Fiquei confuso!

7 respostas

.. editei aqui, e respondi sua pergunta. Pois você marcou o exemplo com o comentário e eu não tinha visto.

Ah, no seu comentário:

 .then(dao => dao.listaTodos())

Qual o valor que then esta retornando? O resultado de dao.listaTodos() que é uma promise. Quando um then retorna uma promise, na próxima chamada encadeada ao then, você tem acesso o valor resolvido da promise.

É isso que evita o callback hell, evitando também o aninhamento de promise dentro de promise.

Então, é justamente nos retornos que eu me perco. Comentei novamente as linhas abaixo

ConnectionFactory
      .getConnection() // Retorna uma Promise
      .then(connection => new NegociacaoDao(connection)) // Constructor, não retorna Promise
      .then(dao => dao.listaTodos()) // Retorna uma Promise
      .then(negociacoes => {
        negociacoes.forEach(negociacao => {
          this._listaNegociacoes.adiciona(negociacao)
        })
      })

A linha .then(connection => new NegociacaoDao(connection)) executa o constructor do NegociacaoDao, que não retorna uma Promise, mas uma instância de NegociacaoDao. Mesmo assim é chamado o .then(dao => dao.listaTodos()) logo em seguida.

A impressão que tenho é que estamos fazendo fazemos a seguinte chamada: {}.then(dao => dao.listaTodos()) onde "{}" é uma instância de NegociacaoDao, e não uma Promise.

Então por quê conseguimos chamar o .then(dao => dao.listaTodos())

Só pensar que then pode retornar qualquer coisa como uma função padrão em JS. Mas se o valor retornado é uma promise é realizado um unwrap de seu valor. Isso evita aninhar uma promise dentro de outra.

ConnectionFactory
      .getConnection() // Retorna uma Promise
      .then(connection => new NegociacaoDao(connection)) //  peguei o retorno da promise retornada. Agora retorno uma instância de Negociação dao. Não retorna promise e não importa
      .then(dao => dao.listaTodos()) // Retorna uma Promise. O valor resolvido da promise será passado para a chamada do then seguinte 
      .then(negociacoes => {
        negociacoes.forEach(negociacao => {
          this._listaNegociacoes.adiciona(negociacao)
        })
      })

O mesmo código poderia ser reescrito assim:

ConnectionFactory
      .getConnection()
      .then(connection => {
          let dao = new NegociacaoDao(connection);
          return dao.listaTodos();
      }) 
      .then(negociacoes => {
        negociacoes.forEach(negociacao => {
          this._listaNegociacoes.adiciona(negociacao)
        })
      })

Dessa forma você precisa abrir um bloco, usar duas instruções e ainda usar a famigerada instrução return. No entanto, é o programador que escolhe aquela forma que ele se sentir mais à vontade.

solução!

Tudo bem agora? Se não foi, não há problema. A gente vai refinando.

Eu acabei perdendo um detalhe sobre as Promises quando fui ler a documentação da MDN:

"...Como os métodos Promise.prototype.then e Promise.prototype.catch retornam promises, eles podem ser encadeados — uma operação chamada composição." (https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise)

Essa confusão foi por causa da emoção do curso! kkkkkkkk Obrigado pela ajuda e paciência, Flavio!

Ainda tenho algumas pequenas dúvidas sobre os padrões de projeto mas vou juntar tudo pra perguntar no final do curso.