Javascript setTimeout работает неожиданно - PullRequest
0 голосов
/ 13 июня 2018

У меня проблемы с функцией setTimeout () в Javascript .. Я хочу отображать секунды в div с id = time .. Но setTimeout () не работает должным образом, потому что обновление не выполняется ровно за 1 секунду .. refresh () является функцией запроса AJAX.

var time = 0;
var url = "";
var tm = 0;
var resp = -1;
function refresh(){ // onload refresh is called();
    if(tm == 0){
        url = "quizload.php";
    }
    else{
       url = "quizload.php?ans=" + resp;
    }
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function(){
        if (this.readyState == 4 && this.status == 200) {
            var a = this.responseText;
            var result = JSON.parse(a);
            document.getElementById("question").innerHTML = result[0];
            document.getElementById("op1").innerHTML = result[1];
            document.getElementById("op2").innerHTML = result[2];
            document.getElementById("op3").innerHTML = result[3];
            document.getElementById("op4").innerHTML = result[4];
            time = result[6] == '1' ? 20 : result[6] == '2' ? 35 : 60; // time = 20
        }
    };
    xhttp.open("GET", url, true);
    xhttp.send();
    tm++;
    if(tm == 11){
        location.href = "result.php";
    }
    update();
}

function update(){
    setTimeout(function(){
        document.getElementById("time").innerHTML = time; // Updation is not exactly 1 second
        time = time - 1; // time is is seconds and value is 20
        if(time == 0){
            refresh(); // Ajax request function
        }
        update();
        },1000);
}

Что я здесь не так делаю?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

сначала может потребоваться инициализировать переменную времени var time = 20 or Date(), а после проверки я работаю для меня

        var time = 20;
        function update(){
            setTimeout(function(){

                console.log(time); // Updation is not exactly 1 second
                time = time - 1; // time is is seconds and value is 20
                if(time == 0){
                    console.log("print refreash")
                    return false;
                }
                update();
                },1000);
        }
        update()

Я получил похожую ошибку, когда я пытаюсь это сделать без инициализации var time = 'value', и я получаю подобное, как вы упомянули

        console.log(time); // Updation is not exactly 1 second
                    ^

ReferenceError: time is not defined
    at Timeout._onTimeout (C:\Users\Manan\Desktop\stack.js:5:21)
    at ontimeout (timers.js:427:11)
    at tryOnTimeout (timers.js:289:5)
    at listOnTimeout (timers.js:252:5)
    at Timer.processTimers (timers.js:212:10)
0 голосов
/ 13 июня 2018

Это обычное явление с синхронизацией почти во всех языках и библиотеках.Вещи никогда не попадут точно в ровное время.

Когда вы используете setTimeout(), вы на самом деле говорите: «По прошествии x миллисекунд, запустите эту функцию».Уловка в том, что она делает другие вещи, поэтому на самом деле происходит после прохода x миллисекунд, эта функция ставится в очередь для вызова, но для ее запуска может потребоваться еще несколько миллисекунд.

Короче говоря,вы не можете создать настоящие часы исключительно в JavaScript, потому что они всегда будут дрейфовать;обычно только на несколько миллисекунд каждый тик, но все хуже и хуже.

let last = Date.now();
let shouldBe = -1000; // account for first tick
let actual = 0;

const run = () => {
  const now = Date.now();
  shouldBe += 1000;
  actual += now - last;
  
  console.log({ sinceLast: now - last, actual, shouldBe, drift: actual - shouldBe });
  
  last = now;
  setTimeout(run, 1000);
};

run();

Однако вы можете использовать setTimeout() с некоторым интервалом (обычно <1 секунда), после чего вы используете объект <code>Date (который может читать данные клиента).системное время), чтобы узнать текущее время и обновить его таким образом.

const clock = document.querySelector('div');

const updateClock = () => {
  const now = new Date();
  clock.innerHTML = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
  setTimeout(updateClock, 500);
};

updateClock(); // start it
<div>XX:XX:XX</div>

Он будет отключен на несколько миллисекунд каждый тик, но он вернется на прежний уровень и не будет иметь большого значения.Это единственный реальный подход, позволяющий делать это с любым уровнем точности.

...