You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript/jQuery中setInterval获取数据总是滞后一次的求助

setInterval获取服务器时间滞后的问题与解决

问题描述

我认为JavaScript中的setInterval()应该在触发间隔的时刻正常工作,但测试发现每次返回的都是上一次间隔的数据。而setTimeout()在每次页面刷新后都能正常工作。

以下函数在客户端移动端从远程服务器获取显示在div中的时间:setTimeout()获取的结果基本正确,客户端与服务器时间一致,存在网络延迟属于正常情况,但无法理解为何setInterval()的结果总是滞后一个间隔。

测试代码

客户端代码

<script>
var href = 'https://some-domain.com';   
function check_time() {         
    $('#timestamp_far').load(''+href+' #timestamp_far');

    setTimeout(function () { 
        element_stamp = document.getElementById('timestamp_far'); 
        stamp_ne = element_stamp.innerText;
        alert(stamp_ne); 
    }, 500);

} // end check_time     

setInterval(check_time, 30*1000);
setTimeout(check_time, 500);
</script>

服务器端PHP代码

<?php 
$date_now_server = date('i:s');
?>
<div id="timestamp_far"> <?php echo $date_now_server; ?></div>

观察现象

  • 客户端当前时间10:10时,setTimeout返回10:12(网络延迟,属正常),setInterval无输出;
  • 客户端当前时间10:40时,setTimeout返回10:45(网络延迟,属正常),setInterval返回10:12(始终显示上一次的时间)。

问题原因

核心问题是你把异步的load()请求和固定延迟的setTimeout绑定在了一起,逻辑存在漏洞:

  • load()是AJAX异步请求,它的完成时间完全取决于网络状况,不是固定的500ms。
  • 你每次调用check_time时,先发起请求,然后不管请求是否成功返回,都固定500ms后去读DOM。如果某次网络卡顿,请求耗时超过500ms,那此时读到的还是上一次请求留下的旧数据。
  • 后续setInterval每隔30s触发一次新请求,但只要某次请求的耗时超过500ms,就会一直读到之前的旧内容,自然出现“滞后一个间隔”的现象。

首次的setTimeout(check_time,500)能正常工作,是因为页面刚加载时没有旧数据,第一次请求大概率会在1000ms内完成,刚好能读到最新内容。

解决方案

不要用固定延迟的setTimeout读取DOM,而是利用load()的回调函数,在请求成功并更新DOM后立即读取数据,这才是可靠的方式。

修改后的客户端代码

<script>
var href = 'https://some-domain.com';   
function check_time() {         
    // 利用load的回调函数,在请求完成、DOM更新后执行读取操作
    $('#timestamp_far').load(href + ' #timestamp_far', function() {
        var element_stamp = document.getElementById('timestamp_far'); 
        var stamp_ne = element_stamp.innerText;
        alert(stamp_ne); 
    });
} // end check_time     

setInterval(check_time, 30*1000);
setTimeout(check_time, 500);
</script>

改进说明

  • load()的第二个参数是回调函数,只有当AJAX请求成功、目标DOM内容更新完成后才会执行,确保你读取的是最新的服务器返回数据。
  • 去掉固定的500ms延迟,彻底避免了网络波动导致的旧数据读取问题。
  • 给变量加上var关键字,避免全局变量污染。

替代方案(更直观)

你也可以用$.get直接获取服务器HTML,再提取目标内容,逻辑更清晰:

<script>
var href = 'https://some-domain.com';   
function check_time() {         
    $.get(href, function(data) {
        // 从返回的HTML中提取服务器时间
        var serverTime = $(data).find('#timestamp_far').text().trim();
        // 更新页面显示
        $('#timestamp_far').text(serverTime);
        alert(serverTime);
    });
} // end check_time     

setInterval(check_time, 30*1000);
setTimeout(check_time, 500);
</script>

这种方式不依赖DOM自动替换,直接处理返回数据,能避免多次load可能带来的潜在冲突。

内容的提问来源于stack exchange,提问作者Shahram Mohseni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:31:04