7
respostas

Promisse.all() para alterar propriedades da página

Olá boa tarde,

Estou implementando o uso de Promise em um código para alterar propriedades da página, e estou aplicando da seguinte forma:

Tenho o botão que ao ser clicado chama a função "loading()" que faz o uso de Promise.all().

        $('.pts-btn-month-view').click( function () {
            console.log('Inicializado');           
            var p = new Promise(function(resolve, reject) {                   
                resolve(loading());
            });

            p.then(function(result) {
                console.log('Finalizado');           
                  return result;
                });
        });

E para cada promise executo uma determinada situação, por exemplo o código do showOverlay() irá exibir um ícone até finalizar o carregamento pesquisa da página.

        var loading = function() {

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

                Promise.all([
                    showOverlay(),
                    loadDisplay(),
                    hideOverlay()    
                ]).then()
                    resolve();
                });
        };

Função para exibir o overlay.

        function showOverlay () { 
            return new Promise ((resolve, reject)=>{ 
                $("#loading").show();
               $("#black-overlay").show();
                  resolve();
            }); 
        }

E para fechar o overlay, temos a função abaixo;

        var hideOverlay = function(){
            return new Promise ((resolve, reject)=>{ 
                $("#loading").hide();
                $("#black-overlay").hide();
                resolve();
            });
        }

Ocorre que tanto o showOverlay() e o hideOverlay() não são executados de acordo com a sequência, eles somente são executados quando finalizar todo o processo. Minha pergunta é se eles não deveriam ser executados assim que a sua promise é chamada?

7 respostas

Boa tarde.

Promise.all funciona assim. Você passa a quantidade de promises que você quer que ele resolva em paralelo. Depois que todas tiverem sido resolvidas, o resultado de cada uma delas é acessível em seu then. Como você pode ver, não há uma sequencia, as promises são resolvidas em paralelo. O que há é a disponibilidade dos dados, depois de todos resolvidos, na mesma sequencia da chamada das promises. Você não esta interessado em dado nenhum, apenas quer que sejam executadas as operações sequencial, não vai funcionar.

Como sugere para que eu possa resolver essa questão para exibir e ocultar o overlay enquanto os processos são executados?

Estou me esforçando para entender seu código e tentar compreender a razão de você estar usando Promise. Não faz sentido nenhum para mim você ter isolado as funções showOverlay e hideOverlay em promises. Em nenhum momento no código que você mostrou há um código assíncrono sequer.

Tenta explicar para mim, detalhadamente o motivo de você ter escrito o código assim e que problema deseja resolver para eu então dar minha opinião. Por que, até onde eu entendi, a sugestão é não usar promises, esse é o problema do seu código.

Eu tenho uma página onde carrego agendamentos para cada dia específico em uma agenda com todos os dias do mês. Ocorre que para carregar essa agenda é realizado um loop para organizar a data específica para cada dia, e esse loop está demorando, e para que o usuário saiba que está carregando eu iria fazer essa chamada.

Anteriormente tentei executar da seguinte forma;

Bloquear

            $("#loading").attr("style","display:block"); 
            $("#black-overlay").attr("style","display:block");

Desbloquear ao finalizar

            $("#loading").attr("style","display:none"); 
            $("#black-overlay").attr("style","display:none");

Mas ao executar desta forma, é executado todas as outras operações, e o loading é chamando somente no final depois ter rodado todo o processo.

Pra resumir, quero um loading na tela enquanto o processo é executado.

Basta você fazer

            $("#loading").attr("style","display:block"); 
            $("#black-overlay").attr("style","display:block");

Antes de chamar sua operação assíncrona, e no then da sua promise que faz o loading fazer:

            $("#loading").attr("style","display:none"); 
            $("#black-overlay").attr("style","display:none");

Flávio eu criei da seguinte forma:

        $('.pts-btn-month-view').click( function () {

            $("#loading").attr("style","display:block"); 
            $("#black-overlay").attr("style","display:block");

            console.log('Inicializado');           
            var p = new Promise(function(resolve, reject) {                   
                resolve(loading());
            });

            p.then(function(result) {
                $("#loading").attr("style","display:none"); 
                $("#black-overlay").attr("style","display:none");
                console.log('Finalizado');           
                return result;
            });
        });

Ao clicar ele não exibe o loading e executa todo o processo, mas ao debugar e marcar a linha dentro do .then(), aí sim é exibido.

Se a sua operação é executada rapidamente ele vai exibir o load e em milésimo de segundos o callback da sua promise vai removê-lo. Não deixe de conferir as aulas de XMLHTTP Request do curso de JavaScript, antes dos cursos avançados para ficar ainda melhor nessa parte de operações assíncronas. Pegou a ideia?