2
respostas

[Dúvida] Timer não atualizando no display quando alterado o contexto

Ao alterar o contexto, o timer não era atualizado, e só alterava após eu clicar pela segunda vez no botão de alterar o contexto (ele exibia o último timer do contexto que estava selecionado)

O que acontecia é que quando eu trocava entre os contextos (foco, descanso curto e descanso longo), o tempo era alterado (como em tempoEmSegundos = 1500 para foco, tempoEmSegundos = 300 para descanso curto e assim por diante), mas o display não era atualizado automaticamente.

A solução foi garantir que sempre que o tempo fosse alterado (por exemplo, ao clicar em um botão de contexto), a função mostrarTimer() fosse chamada imediatamente para refletir a mudança na interface.

O ajuste foi:

  1. Chamar mostrarTimer() imediatamente após a alteração do contexto, para atualizar a tela com o tempo correto logo após mudar o contexto.
  2. Não depender de outro evento para atualizar o timer; cada alteração de contexto deve imediatamente refletir o tempo atual.

Quando fiz essa alteração o código funcionou, mas fica a minha dúvida, deixei passar algo que o instrutor disse?

O código disponibilizado por vocês no github não há essa invocação dentro de cada contexto, ela foi apenas invocada dentro da função alterarContexto(), como o código funcionou dessa maneira?

Código no GitHub:

focoBt.addEventListener('click', () => {
    tempoDecorridoEmSegundos = 1500
    alterarContexto('foco')
    focoBt.classList.add('active')
})

curtoBt.addEventListener('click', () => {
    tempoDecorridoEmSegundos = 300
    alterarContexto('descanso-curto')
    curtoBt.classList.add('active')
})

longoBt.addEventListener('click', () => {
    tempoDecorridoEmSegundos = 900
    alterarContexto('descanso-longo')
    longoBt.classList.add('active')
})

function alterarContexto(contexto) {
    mostrarTempo()
    ...

Código que funcionou para mim:

botaoFoco.addEventListener('click', () => {
    alterarContexto('foco');
    botaoFoco.classList.add('active');
    tempoEmSegundos = 1500;
    mostrarTimer(); //invocando durante a mudança de contexto
});

botaoCurto.addEventListener('click', () => {
    alterarContexto('descanso-curto');
    botaoCurto.classList.add('active');
    tempoEmSegundos = 300;
    mostrarTimer(); //invocando durante a mudança de contexto
});

botaoLongo.addEventListener('click', () => {
    alterarContexto('descanso-longo')
    botaoLongo.classList.add('active');
    tempoEmSegundos = 900;
    mostrarTimer(); //invocando durante a mudança de contexto
});

function alterarContexto(contexto) {
    // mostrarTimer(); //invocando no função, como feito pelo instrutor
2 respostas

Olá, Isabela, como vai?

Esse comportamento acontece porque a ordem de execução no seu código faz com que a atualização do display só aconteça após a mudança de contexto.

No código do instrutor, a função mostrarTempo() é chamada dentro de alterarContexto(), o que garante que o display seja atualizado sempre que o contexto for alterado.

No seu caso, você está definindo tempoEmSegundos após chamar alterarContexto(), então quando mostrarTempo() é executado dentro de alterarContexto(), ainda não houve a atualização do valor. Por isso, você precisou chamar mostrarTimer() novamente após definir tempoEmSegundos.

Foi só uma diferença de organização. Qualquer outra dúvida, o fórum está à disposição.

Espero ter ajudado!

Siga firme nos seus estudos e conte com o fórum sempre que precisar.

Abraços :)

Caso este post tenha lhe ajudado, por favor, marcar como solucionado

Olá, obrigado pela ajuda!

Na verdade o meu código na organização estava idêntico ao do instrutor, eu estava chamando a função dentro de "alterarcontexto" da mesma forma que ele, mas isso fazia com que os botões de foco, descanso curto e longo não atualizassem quando eu trocava de página. Eles apenas eram atualizados quando eu já alterava a página e clicava no botão novamente, e ai o timer ficava correto.

Precisei chamar a função dentro de cada event listener para que funcionasse, segue abaixo meu arquivo script na forma padrão que não funciona, sem eu ter chamado a função individualmente para cada event listener:

const html = document.querySelector('html');
const botaoFoco = document.querySelector('.app__card-button--foco');
const botaoCurto = document.querySelector('.app__card-button--curto');
const botaoLongo = document.querySelector('.app__card-button--longo');
const botoes = document.querySelectorAll('.app__card-button');

//.....................

const banner = document.querySelector('.app__image');

//.....................

const titulo = document.querySelector('.app__title');
const tituloStrong = document.querySelector('.app__title-strong');

//.....................

const timer = document.querySelector('#timer');
const botaoMusica = document.getElementById('alternar-musica')
const textoStartPause = document.querySelector('#start-pause span')
const imgStartPause = document.querySelector('#start-pause img')
// const botaoStarPause = document.getElementById('start-pause'); //botaoStartPause.childNodes[3]
const musica = new Audio('sons/luna-rise-part-one.mp3');
const somPlay = new Audio('sons/play.wav');
const somPause = new Audio('sons/pause.mp3');
const somBeep = new Audio('sons/beep.mp3');

let tempoEmSegundos = 1500;
let intervaloID = null;

musica.loop = true;

//..................... FUNCIONALIDADES ..................//

function alterarContexto(contexto) {
    mostrarTimer();
    botoes.forEach(function (contexto){
        contexto.classList.remove('active');
    })
    html.setAttribute('data-contexto', contexto)
    banner.setAttribute('src', `/imagens/${contexto}.png`)
    switch (contexto) {
        case 'foco':
            titulo.childNodes[0].nodeValue = `Otimize sua produtividade,`;
            titulo.childNodes[3].nodeValue = `mergulhe no que importa`;
            break;

        case 'descanso-curto':
            titulo.childNodes[0].nodeValue = `Que tal dar uma respirada?`;
            titulo.childNodes[3].nodeValue = `Faça uma pausa curta!`;
            break;

        case 'descanso-longo':
            titulo.childNodes[0].nodeValue = `Hora de voltar à superfície.`;
            titulo.childNodes[3].nodeValue = `Faça uma pausa longa`;
            break;
        default:

            break;
    }
}

botaoMusica.addEventListener('change', () => {
    if (botaoMusica.checked) {
        musica.play();
    } else {
        musica.pause();
    }
})

botaoFoco.addEventListener('click', () => {
    alterarContexto('foco');
    botaoFoco.classList.add('active');
    tempoEmSegundos = 1500;
});

botaoCurto.addEventListener('click', () => {
    alterarContexto('descanso-curto');
    botaoCurto.classList.add('active');
    tempoEmSegundos = 300;
});

botaoLongo.addEventListener('click', () => {
    alterarContexto('descanso-longo')
    botaoLongo.classList.add('active');
    tempoEmSegundos = 900;
});




const contagemRegressiva = () => {
    if(tempoEmSegundos <= 0) {
        somBeep.play();
        alert('Tempo finalizado!')
        zerar();
        return;
    }
    tempoEmSegundos -= 1
    //mostrarTimer();
}

const botaoStartPause = document.querySelector('#start-pause')
botaoStartPause.addEventListener('click', (iniciarOuPausar));

function iniciarOuPausar() {
    if(intervaloID){
        zerar();
        somPause.play();
        return;
    }
    somPlay.play();
    somBeep.pause();
    intervaloID = setInterval(contagemRegressiva, 1000);
    textoStartPause.textContent = 'Pausar';
    imgStartPause.setAttribute('src', `/imagens/pause.png`);
}

function zerar() {
    clearInterval(intervaloID);
    intervaloID = null;
    textoStartPause.textContent = 'Começar';
    imgStartPause.setAttribute('src', `/imagens/play_arrow.png`);
}

function mostrarTimer() {
    const tempo = new Date(tempoEmSegundos * 1000);
    const tempoFormatado = tempo.toLocaleTimeString('pt-Br', {minute: '2-digit', second: '2-digit'})
    timer.innerHTML = `${tempoFormatado}`;
}

mostrarTimer();