JavaScript 几个小时后递归 setTimeout() 无法正常工作

JavaScript recursive setTimeout() not working correctly after few hours

在我的网络应用程序中,我使用递归 setTimeout() 每秒调用一个函数(见下文)。

function test() {
    console.log('test');
    setTimeout(test, 1000);
}

test();

它运行良好,但大约 6 小时后,它每 3 秒左右调用一次 test() 函数。 (setInterval()有同样的问题)

该程序需要 运行 一天 24 小时,并且必须每秒更新。任何解决此问题的想法。

完整代码如下:

function updateDateTime() {
    var now = new Date();
    
    /* Date */
    var woy = moment(now).format('W');
    var dow = now.getDay();
    var d = now.getDate();
    var m = now.getMonth();
    var y = now.getFullYear();
    document.getElementById('date_day').innerHTML = daysOfWeek[dow];
    document.getElementById('date').innerHTML = d + ". " + monthsOfYear[m] + " " + y;
    document.getElementById('date_week').innerHTML = "KW " + woy;

    /* Time */
    var h = now.getHours();
    var m = now.getMinutes();
    var s = now.getSeconds();
    m = checkTime(m);
    s = checkTime(s);
    
    /*if(odd)*/
        $("#time_colon").css('visibility', 'visible');
    /*else
        $("#time_colon").css('visibility', 'hidden');
    odd = !odd;*/
    
    document.getElementById('time_h').innerHTML = h;
    document.getElementById('time_m').innerHTML = m;
    document.getElementById('time_s').innerHTML = s;
    
    /* Clock */
    drawClock(now);
    
    setTimeout(updateDateTime, 1000 - moment().milliseconds() + 50);
}

function checkTime(i) {
  if (i < 10) {i = "0" + i};
  return i;
}

还有一些其他函数应该每 15 分钟更新一次 Ajax 这样的请求:

function updateNews() {
    var xmlhttp = new XMLHttpRequest();
    var url = "newsapi";
    xmlhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            document.getElementById('news').innerHTML = '';
            var news = JSON.parse(this.responseText);
            for(e in news){
                data = news[e];
                document.getElementById('news').innerHTML += '<span class="mx-3">'+data.title+'</span>';
                if(e < news.length) {
                    document.getElementById('news').innerHTML += ' &middot; ';
                }
            }
        }
    };
    xmlhttp.open("GET", url, true);
    xmlhttp.send();
    
    setTimeout(updateNews, 1800*1000);
}

我还使用代码为 chrome 浏览器禁用屏幕睡眠模式:

if ('wakeLock' in navigator) {
    // Screen Wake Lock API supported 
    // The wake lock sentinel.
    let wakeLock = null;
    
    // Function that attempts to request a screen wake lock.
    const requestWakeLock = async () => {
        try {
            wakeLock = await navigator.wakeLock.request();
            wakeLock.addEventListener('release', () => {
                console.log('Screen Wake Lock released:', wakeLock.released);
            });
            console.log('Screen Wake Lock released:', wakeLock.released);
        } catch (err) {
            console.error(`${err.name}, ${err.message}`);
        }
    };
    
    // Request a screen wake lock…
    requestWakeLock();
}

如果您需要更多信息,请发表评论。

最新更新: 今天早上我看到因为我的服务器崩溃,新闻数据没有更新,但是12个小时左右时间仍然是正确的。但是 4 小时后,在我重新启动服务器和时钟后,时间偏移了 2 秒。所以我猜setTimeout的偏移量取决于其他超时中的Ajax请求。

这是我的结果列表:

|超时值 |设备 |偏移 |浏览器 |
| 1000 - 时刻().毫秒() + 50 |树莓派 |大约 4-6 小时后 2 秒 | chrome & 火狐 |
| 1000 - 时刻().毫秒() + 50 |树莓派 |没有偏移但没有工作 ajax 请求 | chrome |
| 1000 |树莓派 |大约 4-6 小时后大约 2 秒 | chrome & 火狐 |
| 500 |树莓派 |大约 4-6 小时后大约 2 秒 | chrome & 火狐 |

我解决了问题。

您只需在 Ajax 请求完成后调用 setTimeout() 事件。