javascript 带clearInterval的计数器,单击按钮后不重新启动

x8diyxa7  于 2023-01-29  发布在  Java
关注(0)|答案(2)|浏览(127)

有一个单词翻译卡片页面,包括:
1.一个3秒倒计时,运行后立即加载页面,当您移动到一个新的词后,按下“更正”按钮。
1.按下“优秀”按钮后出现的单词及其翻译。此按钮停止并隐藏计数器。
1.如果3秒内未按下“优秀”,则显示“显示答案”按钮。
1.按下“优秀”或“显示答案”按钮时出现的“错误”和“正确”按钮。
问题是倒计时是如何工作的(不稳定)。有时候点击“更正”后它不会重新启动。我尝试过在单独的函数中管理倒计时,但这种方法提供了更多的问题。所以现在有一个全局调用的计时器和一个当你点击“更正”按钮时调用的计时器。我认为问题是在timerId附近。我将很高兴对代码的任何评论和想法。

<div class="deck-container">
    <div class="words-container">
        <h2 id="primary-word"></h2>
        <h2 id="secondary-word"></h2>
    </div>

    <div class="btn-container">
        <p id="timer-count">3</p>
        <button id="btn-excellent" onClick="excellent()">Excellent!</button>
        <button id="btn-show-answer" onClick="showAnswerF()">Show Answer</button>
        <button id="btn-wrong">Wrong</button>
        <button id="btn-correct" onClick="correctF()">Correct</button>
    </div>
</div>
let currentWord = 0
let timerCount = 3
let fetched_data = {}

async function getDeck () {
    let response = await fetch('/api/deck_words/2/', {
        method: 'get',
        headers: {
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application/json'
            }
        }
    )
    let data = await response.json()
    let primaryElement = document.getElementById('primary-word')
    primaryElement.innerText = await data[currentWord]['primary_word']
    let secondaryElement = document.getElementById('secondary-word')
    secondaryElement.innerText = await data[currentWord]['secondary_word']
    return data
}

fetched_data = getDeck()

const getData = async () => {
    return await getDeck()
}

data = getData();

function countDecrease() {
    timerCount --
    if (timerCount > 0) {
        document.getElementById("timer-count").innerHTML = timerCount
    } else {
         hideExcellent()
    }
}

function hideExcellent() {
    showElement(true,'btn-excellent')
    showElement(true,'timer-count')
    showElement(false,'btn-show-answer')
}

let timerId = setInterval(() => countDecrease(), 1000)

setTimeout(() => {
    clearInterval(timerId)
}, 3000)

function showElement(showProperty, elementClass) {
    showProperty = !showProperty
    let element = document.getElementById(elementClass)
    element.style.display = (showProperty  === true) ? "inline-block" : "none";
}

function showAnswerF() {
    showElement(true,'btn-show-answer')
    showElement(false,'secondary-word')
    showElement(false,'btn-wrong')
    showElement(false,'btn-correct')
}

function excellent() {
    showElement(true,'timer-count')
    showElement(true,'btn-excellent')
    showElement(false,'btn-wrong')
    showElement(false,'btn-correct')
    showElement(false,'secondary-word')
    clearInterval(timerId)
    timerCount = 3
}

function correctF() {
    currentWord++
    const changeWords = () => {
        fetched_data.then((data) => {
        document.getElementById('primary-word').innerText = data[currentWord]['primary_word']
        document.getElementById('secondary-word').innerText = data[currentWord]['secondary_word']
        document.getElementById("timer-count").innerText = '3'

        timerCount = 3

        timerId = setInterval(() => countDecrease(), 1000)

        setTimeout(() => {
            clearInterval(timerId)
        }, 3000)
      })
    }
    changeWords()

    let countElement = document.getElementById('timer-count')
    countElement.style.display = "block"
    showElement(false,'btn-excellent')
    showElement(true,'btn-wrong')
    showElement(true,'btn-correct')
    showElement(true,'secondary-word')
}
ljo96ir5

ljo96ir51#

这是倒计时。第一次倒计时是在1秒后。

let count = 3;
let timer = [];

const start = () => {
  new Array(count).fill(true).forEach((_,i) => { 
    timer.push(setTimeout(() => console.log('count',count - i),(i+1) * 1000))
  })
}

const stop = () => timer.forEach(clearTimeout);
<button onclick="stop()">STOP</button>
<button onclick="start()">START</button>
nwsw7zdq

nwsw7zdq2#

我认为这将是一个更好的处理异步函数,也许这样。

const timerCount = document.querySelector("#timer-count")
const reset = document.querySelector("button")

function delay(ms) {
    return new Promise(res => setTimeout(res, ms))
}

async function countDown(signal) {
    const aborted = new Promise(resolve => signal.addEventListener("abort", resolve))
    for (let i = 10; i >= 0 && signal?.aborted != true; --i) {
        timerCount.textContent = i
        await Promise.race([delay(1000), aborted])
    }
    timerCount.textContent = ""
}

async function startCountdown() {
    const ac = new AbortController()
    const abort = () => ac.abort()
    reset.addEventListener("click", abort, { once: true })
    reset.textContent = "Cancel"
    await countDown(ac.signal)
    reset.removeEventListener("click", abort)
    reset.addEventListener("click", startCountdown, { once: true })
    reset.textContent = "Start"
}

startCountdown()
<p id="timer-count"></p>
<button>Start</button>

或者,您可能希望将倒计时建模为实现EventTarget的对象。
一个二个一个一个

相关问题