首页 > 解决方案 > Jquery/Javascript:倒数计时器动作不规律

问题描述

我正在尝试使用带有定时问题的 javascript 进行简单的测验。每个问题持续 10 秒,然后继续下一个问题。倒数计时器在第一个问题上表现良好,之后它开始加快速度或显示以下问题的随机数。这是我的代码,PS 我为效率低下和繁忙的代码道歉,我对 javascript 还是很陌生,一旦我解决了这个问题,我会让代码更加精简。

var questionList = [
        {
            q:"What is a dog?",
            a:["fish","mammal","plant","prokaryote"],
            answer: 1
        },
         {
            q:"What is a cat?",
            a:["mammal","fish","plant","amphibian"],
             answer: 0
        },
         {
            q:"What is a tree?",
            a:["plant","fish","mammal","none"],
             answer: 0
        },
         {
            q:"What do cars run on?",
            a:["gasoline","water","ethanol","liquid oxygen"],
             answer: 0
        },
        {
            q:"What is 4 x 4?",
            a:["8","16","4","160"],
            answer: 1
        },
        {
            q:"What is the capital of Australia?",
            a:["Brisbane","GoldCoast","Perth","Canberra","Melbourne"],
            answer: 3
        },
        {
            q:"What is the national flower of Canada?",
            a:["sunflower","daisy","trillium","rose","lotus"],
            answer: 2
        }
    ];
    //--------------------------------------
    var picked;
    var qcount = 0;
    var output = [];
    var timer;
    var timer2;
    var timeLeft = 10;
    var correctQ = 0;
    var wrongQ = 0;
    //var randomQ = Math.floor(Math.random()*7);
    var x = questionList[qcount];
    var j = x.answer;
   // var cAns = x.a[j];
    //console.log(cAns);
    console.log(j);
    //new Q w/ options
    function qGen(){
        timer = setInterval(time, 1000)
        $('#question').text(x.q);
        for (var i=0; i < (x.a).length; i++){
            var newLi = $('<button>');
            newLi.attr('data-id', i);
            newLi.addClass("answer").text(x.a[i]);
            $('#list').append(newLi);
        }
    }
    qGen();
    // correct answer
    function clickChoice(){
      $('#list').on("click",'button', function(){
          picked = parseInt($(this).attr("data-id")); 
          console.log(picked + "    click");
           if (picked === j){
               console.log(j + "    if");
               qcount++;
               x = questionList[qcount]; 
               j = x.answer;
               qGen();
               correct();
           }else{
               qcount++;
               incorrect();
                x = questionList[qcount]; 
               j = x.answer;
               qGen();
           }
    })
    }
    clickChoice();
    //timer
    function time(){
        timeLeft--;
        $('#time').text(timeLeft);
        if(timeLeft===0){
            $('#score').text('TIME UP');
             timer2 = setInterval(timeUp, 2000);
        }
    }
    //time up
    function timeUp(){
        clearInterval(timer);
        wrongQ++;
        qcount++;
        x = questionList[qcount]; 
        j = x.answer;
        clearInterval(timer2);
        nextQ();
    }
    //correct
    function correct(){
        clearInterval(timer);
        clearInterval(timer2);
        $("#list").text("");
        correctQ++;
        nextQ();
    }
    //incorrect
    function incorrect(){
        clearInterval(timer);
        clearInterval(timer2);
        $("#list").text("");
        wrongQ++;
        nextQ();
    }
    //next question gen
    function nextQ(){
        timeLeft= 10;
        $('#score').text("");
        $('#ca').text("");
        $('#question').text(x.q);
        //$("#time").text(timeLeft);
        $("#list").text("");
        qGen();
    }

标签: javascriptjqueryhtml

解决方案


以下是您的代码的修改版本,应该可以解决您的问题。

笔记

  • 我对你HTMLCSS
  • 我还没有实现score更新,但是鉴于以下内容,这应该是直截了当的

const questionList = [
  {
    q: 'What is a dog?',
    a: ['fish', 'mammal', 'plant', 'prokaryote'],
    answer: 1
  },
  {
    q: 'What is a cat?',
    a: ['mammal', 'fish', 'plant', 'amphibian'],
    answer: 0
  },
  {
    q: 'What is a tree?',
    a: ['plant', 'fish', 'mammal', 'none'],
    answer: 0
  },
  {
    q: 'What do cars run on?',
    a: ['gasoline', 'water', 'ethanol', 'liquid oxygen'],
    answer: 0
  },
  {
    q: 'What is 4 x 4?',
    a: ['8', '16', '4', '160'],
    answer: 1
  },
  {
    q: 'What is the capital of Australia?',
    a: ['Brisbane', 'GoldCoast', 'Perth', 'Canberra', 'Melbourne'],
    answer: 3
  },
  {
    q: 'What is the national flower of Canada?',
    a: ['sunflower', 'daisy', 'trillium', 'rose', 'lotus'],
    answer: 2
  }
];
//--------------------------------------
let picked;
let qcount = 0;
const output = [];
let timer;
const startingTime = 10;
let timeLeft;
let correctQ = 0;
let wrongQ = 0;
// var randomQ = Math.floor(Math.random()*7);
// let x = questionList[qcount];
// let j = x.answer;
// var cAns = x.a[j];
// console.log(cAns);
// console.log(j);

// next question gen
function nextQ() {
  timeLeft = 10;
  document.querySelector('#score').textContent = '';
  // document.querySelector('#ca').textContent = '';
  document.querySelector('#question').textContent = questionList[qcount].q;
  // $("#time").text(timeLeft);
  document.querySelector('#list').textContent = '';
  qGen();
}

// time up
function timeUp() {
  clearInterval(timer);
  wrongQ += 1;
  qcount += 1;
  nextQ();
}

// correct
function correct() {
  clearInterval(timer);
  correctQ += 1;
  nextQ();
}

// incorrect
function incorrect() {
  clearInterval(timer);
  wrongQ += 1;
  nextQ();
}

// timer
function time() {
  timeLeft -= 1;
  document.querySelector('#time').textContent = timeLeft;
  if (timeLeft === 0) {
    document.querySelector('#score').textContent = 'TIME UP';
    timeUp();
  }
}

// Add EventListener to each button
function addEL(el) {
  el.addEventListener('click', event => {
    picked = parseInt(event.currentTarget.getAttribute('data-id'), 10);
    console.log(`${picked} click`);
    const correctAnswer = questionList[qcount].answer;
    qcount += 1;
    if (picked === correctAnswer) {
      console.log(`${correctAnswer} if`);
      correct();
    } else {
      incorrect();
    }
  });
}

// new Q w/ options
function qGen() {
  const x = questionList[qcount];
  timeLeft = startingTime;
  document.querySelector('#time').textContent = startingTime;
  document.querySelector('#question').textContent = x.q;
  for (let i = 0; i < x.a.length; i += 1) {
    const newLi = document.createElement('li');
    const answer = document.createElement('button');
    answer.setAttribute('data-id', i);
    answer.classList.add('answer');
    answer.textContent = x.a[i];
    addEL(answer);
    newLi.appendChild(answer);
    document.querySelector('#list').appendChild(newLi);
  }
  timer = setInterval(time, 1000);
}

document.addEventListener('DOMContentLoaded', () => {
  qGen();
});
.answer {
  background-color: yellow;
}
<div>
  Question:
  <span id="question">XXX</span>
</div>
<div>
  Time:
  <span id="time">XXX</span>
</div>
<div>
  Score:
  <span id="score">XXX</span>
</div>
<div>
  <ul id="list">
  </ul>
</div>

以下是我所做的更改,包括一些关于 JavaScript 良好实践的提示。

代码逻辑

  • 你打qGen了两次电话,每次点击有效地增加了两个新的间隔
  • 必须将事件侦听器添加到所有按钮
  • 不需要第二个计时器
  • /内部只<li>允许使用元素<ul><ol>
    • 将其他元素(例如按钮)放置在这些<li>s 中是非常好的。
    • 如果您愿意,您也可以采用不同的格式(例如在一行上)
  • 避免在 DOM 树完成加载之前对 DOM 进行操作
    • 查看添加的DOMContentLoaded事件监听器
  • output, correctQ, wrongQ: 这些分配的值永远不会在您的代码中使用

良好实践

  • 避免一元运算符 ++ 和 --
  • 在调用函数之前定义函数
  • 在完全熟悉 vanilla JavaScript 之前,不要使用 jQuery(或其他抽象)
  • 喜欢箭头函数而不是匿名函数
    • 使用event.currentTarget而不是this内部事件侦听器

推荐阅读