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

Promise dependente de outra promise

Boa tarde,

se eu tiver uma promise que é depende da promise anterior, eu tenho que fazer o aninhamento em callback né? Ou o Promise.all resolveria?

promiseA.then( value => { promiseB.then( value => 
    // aqui vou utilizar um valor da promiseA por exemplo
)});
6 respostas

Creio que fica a sua escolha, o problema de ir aninhando uma a uma é que pode virar um callback hell.

Outra coisa, se não me engano o Promise.all vai disparar tudo e se uma der erro cancela tudo também.

Da uma lida nessa documentação aqui: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Vou dar uma lida na documentação Jhosef, obrigado!

Oi Addler, se não me engano, em um exercício eu deixo isso mais claro e no terceiro módulo que esta por vir eu ataco esse ponto mais uma vez. Deixa eu pegar seu exemplo:

promiseA.then( value => { promiseB.then( value => 
    // aqui vou utilizar um valor da promiseA por exemplo
)});

Você pode fazer assim:

promiseA()
   .then(valorPromiseA => promiseB(valorPromiseA))
   .then(valorPromiseB => console.log(valorPromiseB));

Alguns macetes de promise foram omitidos deste módulo para evitar bombardear o aluno. Vamos entender o exemplo acima:

promiseA é uma função ou método que ao ser chamado devolve seu valor no encademanento de then. Nele, veja que passamos o valor resultante para a promiseB. Como estamos usando arrow function, promiseB(valorPromiseA) é retornado pelo then. Tudo que é retornado pelo then é acessível encadeando-se mais uma vez a chamada à then. Na segunda chamada de then, temos o resultado valorPromiseB que foi calculado pela promiseB e que levou em consideração para o cálculo o valor da promiseA. Por fim, imprimimos o resultado final.

Vejamos um exemplo do código da classe NegociacaoService. É um código que você construirá no próximo módulo:

// método da classe `NegociacaoService`. 
lista() {

        return ConnectionFactory
            .getConnection()
            .then(connection => new NegociacaoDao(connection))
            .then(dao => dao.listaTodos())
            .catch(erro => {
                console.log(erro);
                throw new Error('Não foi possível obter as negociações');
            });
    }

Veja que ele faz.ConnectionFactory.getConnection() é uma promise que retorna uma conexão para o IndexedDB. Não queremos trabalhar com a connection, mas com o NegociacaoDao que depende da connection em seu construtor. Repare esta linha:

            .then(connection => new NegociacaoDao(connection))

Nossa arrow function retornará uma nova instância de NegociacaoDao. **Se você retornar qualquer valor em then, o valor estará disponível encadeando-se uma nova chamada à função then. Por isso temos:

            .then(connection => new NegociacaoDao(connection))
            .then(dao => dao.listaTodos())

Veja que agora temos acesso ao dao. Mas não é o dao que queremos, são todas as negociações gravadas no IndexedDB. Daí chamamos o método dao.listaTodos() que retorna uma promise. **Se você retorna uma promise em then, o valor da promise será acessível encadenando-se uma chamada a then.

Veja que em nenhum momento em lista() eu acesso o resultado de dao.listaTodos(). Quem vai acessar é quem chamar o método lista de NegociacaoService. Um exemplo:

new NegociacaoService().listaTodos().then(negociacoes => console.log(negociacoes).

No próximo módulo eu mostro com mais detalhes isso, mas vou resumir:

**Se uma promise retorna em then um valor, esse valor será acessível encadeando-se uma chamada à função then`.

Se uma promise retorna outra promise`, o valor dessa promise também é acessível encadeando-se uma chamada à função then.

Consegui esclarecer ou compliquei com um exemplo que ainda não faz parte do módulo 2 no qual você esta cursando?

Abre o jogo, se não ficou claro, eu faço um exemplo aqui mais simples, mas nem por isso menos importante.

solução!

Tenho um exemplo mais simples que mostra ainda mais o poder das promises:

    <script>

        function promiseA() {

            return new Promise((resolve, reject) => {

                // demora dois segundo para ser executada e seu resultado será 10
                setTimeout(()=> resolve(10), 2000);
            })
        }

        function promiseB(valor) {

            return new Promise((resolve, reject) => {

                // demora um segundo para ser executada e seu resultado será o valor passado de promiseA vezes 2!
                setTimeout(()=> resolve(valor * 2), 1000);
            })
        }  

        promiseA()
            .then(retornoA => promiseB(retornoA))
            .then(retornoB => console.log(retornoB));      
    </script>

Veja que a promiseA demora mais para executar do que a promiseB, mas como estamos encadeando as promises, uma será executada depois da outra em ordem. Quando você tem muita promise nesse sentido, o promise.all é uma boa pedida!. Isso evita encadear várias vezes uma chamada ao then.

Veja que essa forma é muito melhor do que se tivéssemos feito:

        promiseA()
            .then(retornoA => {
                promiseB(retornoA)
                    .then(function(retornoB) {
                        console.log(retornoB)
                    });
            });

Oi Flavio, obrigado pelo retorno! Sensacional as duas respostas, porém o segundo exemplo acho que foi mais simples de entender o funcionamento. Mas os dois exemplos são totalmente construtivos para o nosso conhecimento. Obrigado.

Mais uma dica: use promise.all quando uma promise não depende de outra. No meu exemplo uma promise depende do resultado de outrs.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software