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

AJAX切换时区时JavaScript动态时钟闪烁问题求助

动态时钟AJAX切换时区后闪烁异常问题

我需要实现一个每秒(或每分钟)更新的动态时钟,但通过下拉菜单切换时区触发AJAX请求时出现以下异常:

  • 页面重载设置时区(如Asia/Tokyo)时,时钟显示正常;
  • 通过AJAX切换至其他时区(如Europe/Berlin)后,时钟会在新旧时区时间间每秒闪烁——setInterval每秒执行showTime更新时显示新时区时间,两次更新间隙则回退到原时区时间;
  • 当前输出带GMT后缀,需去除该后缀(优先级较低)。

无法复现问题的原因是时区参数来自AJAX请求(下拉菜单)而非硬编码,相关代码如下:

<?php
$timezone = 'Asia/Tokyo';
//  $timezone = 'America/New_York';
//  $timezone = 'Europe/Berlin';
//  $timezone = 'Asia/Singapore';
        
$datetime = new DateTime('now', new DateTimeZone($timezone));
$formattedDate = $datetime->format('Y-m-d H:i:s');
        
echo '$timezone = ' . $timezone;
echo '<br>';
echo '<pre>';
print_r($datetime);
echo '</pre>';
echo '$formattedDate Shows Static Time in ' . $timezone . ' = ' .  $formattedDate;
echo '<br><br>';
        
echo '
<script>
(function() {
    var serverTime = new Date("' . $formattedDate . '");
    var serverOffset = serverTime.getTime() - new Date().getTime();
        
    function showTime() {
        var now = new Date();
        var correctTime = new Date(now.getTime() + serverOffset);
        
        var formattedTime = correctTime.getFullYear() + "-" +
                            String(correctTime.getMonth() + 1).padStart(2, "0") + "-" +
                            String(correctTime.getDate()).padStart(2, "0") + " " +
                            String(correctTime.getHours()).padStart(2, "0") + ":" +
                            String(correctTime.getMinutes()).padStart(2, "0") + ":" +
                            String(correctTime.getSeconds()).padStart(2, "0");
        
        
        document.getElementById("current-time9").textContent = correctTime;
    }
        
    setInterval(showTime, 1000); // Update every second
})();
</script>
      
<span>current-time9  </span><span id="current-time9"></span><br><br>
';
?>
解决方案

1. 清除旧定时器,避免多实例冲突

AJAX切换时区后,旧的setInterval定时器仍在后台运行,新旧两个定时器交替修改DOM内容,这是闪烁的核心原因。每次加载新时区的脚本前,必须先清除之前的定时器:

  • 在全局作用域定义变量存储定时器ID:
// 全局变量,用来存定时器ID
let timeInterval = null;
  • 在新的时钟脚本初始化时,先清除旧定时器:
(function() {
    // 先清除旧的定时器
    if (timeInterval) clearInterval(timeInterval);
    
    var serverTime = new Date("' . $formattedDate . '");
    var serverOffset = serverTime.getTime() - new Date().getTime();
    
    function showTime() {
        var now = new Date();
        var correctTime = new Date(now.getTime() + serverOffset);
        
        var formattedTime = correctTime.getFullYear() + "-" +
                            String(correctTime.getMonth() + 1).padStart(2, "0") + "-" +
                            String(correctTime.getDate()).padStart(2, "0") + " " +
                            String(correctTime.getHours()).padStart(2, "0") + ":" +
                            String(correctTime.getMinutes()).padStart(2, "0") + ":" +
                            String(correctTime.getSeconds()).padStart(2, "0");
        
        // 使用格式化好的字符串,不要直接赋值Date对象
        document.getElementById("current-time9").textContent = formattedTime;
    }
    
    // 存储新的定时器ID到全局变量
    timeInterval = setInterval(showTime, 1000);
})();

2. 修复时间赋值错误

原代码直接将correctTime(Date对象)赋值给textContent,浏览器会自动转换为带GMT后缀的字符串,同时也会间接加剧闪烁问题。改用已经格式化好的formattedTime字符串,既能精准控制显示格式,又能自然去除GMT后缀。

3. 确保全局变量可访问

如果AJAX是动态将脚本插入页面的,必须保证timeInterval是全局作用域变量,否则每次AJAX请求都会创建新的局部变量,无法清除旧定时器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:14:55