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

问题描述

在我的 Web 应用程序中,我使用递归 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 秒 |铬和火狐|
| 1000 - 时刻()。毫秒()+ 50 |拉斯皮|没有偏移但没有工作 ajax 请求 |铬 |
| 1000 |拉斯皮|大约 4-6 小时后大约 2 秒 |铬和火狐|
| 500 |拉斯皮|大约 4-6 小时后大约 2 秒 |铬和火狐|

解决方法

我解决了这个问题。

您只需要在 Ajax 请求完成时调用 setTimeout() 事件即可。