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

自动刷新Div与新行数据:仅新增数据库条目时触发声音告警

问题分析与解决方案

1. 为什么声音会无差别重复播放?

你的代码里有两个核心问题导致声音每次刷新都会触发:

  • 触发条件太过宽泛:在updateHistory的AJAX成功回调中,只要server_response != '1'就会调用playAlert(),但你的PHP脚本每次都会返回所有events的列表(永远不会等于'1'),所以每20秒刷新一次就会强制播放声音,完全没做"是否有新数据"的判断。
  • 空值判断语法错误:代码里if (server_response.length = 0)是赋值操作(用了=而非判断相等的==),这个条件永远不会成立,导致后续的return永远不会执行——不管返回内容是空还是旧数据,都会走到播放声音的逻辑。

2. 如何基于ID/Timestamp控制仅新条目时播放声音?

我们可以通过记录最后一次获取的最新数据ID(ID是自增唯一值,比timestamp更可靠),每次请求时把这个ID传给后端,让后端只返回比这个ID大的新条目;前端再根据是否收到新内容,决定是否播放声音。

修改步骤:

第一步:修改前端JavaScript代码

新增变量存储最后一次的最新ID,修改请求逻辑传递该ID,并根据返回的新数据判断是否播放声音:

var env = findBootstrapEnvironment();
var audioElement = new Audio();
// 新增:存储最后一次获取的最新事件ID,初始值设为0
var lastEventId = 0;

function playAlert(ignore_checked) {
  if (ignore_checked || (document.getElementById('play_sound') && document.getElementById('play_sound').checked)) {
    if (!document.contains(audioElement)) {
      document.body.appendChild(audioElement);
    }
    if (audioElement.canPlayType("audio/mp3")) {
      audioElement.src = 'notify.mp3';
    } else if (audioElement.canPlayType("audio/wav") || audioElement.canPlayType("audio/x-wav")) {
      audioElement.src = 'notify.wav';
    }
    if (audioElement.currentTime) {
      audioElement.currentTime = 0;
    }
    audioElement.play();
  }
}

function updateHistory() {
  // 把lastEventId作为参数传给后端
  var datastring = 'last_id=' + lastEventId;
  jQuery.ajax({
    type: 'GET',
    url: 'connect.php',
    data: datastring,
    dataType: 'json', // 指定响应为JSON格式,方便处理数据
    success: function (server_response) {
      // 后端返回的是包含新内容HTML和最新ID的对象
      if (server_response.new_html) {
        // 有新内容:更新页面、显示提示、修改标题
        $('#newposts').prepend(server_response.new_html); // 用prepend保留历史内容,新内容置顶
        document.getElementById('updatewarning').innerHTML = '<p><strong>There have been updates to this page.</strong> Please view the updates.</p>';
        document.getElementById('updatewarning').style.display = 'block';
        
        var title = document.title;
        title = title.replace("UPDATED - ", "");
        document.title = "UPDATED - " + title;
        
        // 播放告警声音
        playAlert();
        // 更新lastEventId为最新的条目ID
        lastEventId = server_response.latest_id;
      } else {
        // 无新内容:隐藏提示(可选操作)
        document.getElementById('updatewarning').style.display = 'none';
        // 不播放声音
      }
    }
  });
  // 替换字符串形式的函数调用,直接传函数引用更规范
  setTimeout(updateHistory, 20000);
}

updateHistory();

function findBootstrapEnvironment() {
  var envs = ['xs', 'sm', 'md', 'lg'];
  var $el = $('<div>');
  $el.appendTo($('body'));
  for (var i = envs.length - 1; i >= 0; i--) {
    var env = envs[i];
    $el.addClass('hidden-'+env);
    if ($el.is(':hidden')) {
      $el.remove();
      return env;
    }
  }
}

第二步:修改PHP后端代码(connect.php)

接收前端传来的last_id,仅查询ID大于该值的新事件,返回JSON格式的结果:

<?php
$host="localhost";
$username="root";
$pass="";
$dataname="testdb";

// 直接在连接时指定数据库,避免额外的select操作
$connect = mysqli_connect($host, $username, $pass, $dataname) or die("Could not connect: " . mysqli_error($connect));

// 获取前端传来的last_id,默认值为0
$last_id = isset($_GET['last_id']) ? intval($_GET['last_id']) : 0;

// 仅查询ID大于last_id的新事件,按ID倒序排列
$sql = "SELECT * FROM events WHERE id > $last_id ORDER BY id DESC";
$result = mysqli_query($connect, $sql);

$new_html = '';
$latest_id = $last_id; // 默认保留原ID,有新数据时更新

if(mysqli_num_rows($result) > 0){
    $new_html .= "<div><ul>";
    while($row = mysqli_fetch_array($result)) {
        $new_html .= "<li><span>" . $row['time'] . "</span></li>";
        // 更新latest_id为当前最新的条目ID(因倒序,第一行就是最新的)
        if($row['id'] > $latest_id){
            $latest_id = $row['id'];
        }
    }
    $new_html .= "</ul></div>";
}

// 返回JSON格式的响应数据
echo json_encode([
    'new_html' => $new_html,
    'latest_id' => $latest_id
]);

mysqli_close($connect);
?>

额外优化说明:

  • 用prepend替代html()更新页面,保留历史数据的同时让新内容置顶,提升用户体验;
  • 修复了原PHP代码中mysqli_select_db的变量错误(原代码用了未定义的$con);
  • 把setTimeout的字符串调用改成函数引用,避免性能损耗和潜在风险;
  • 后端返回JSON格式数据,让前端处理逻辑更清晰。

这样修改后,只有当数据库中出现ID大于lastEventId的新条目时,前端才会触发声音告警,完美解决无差别播放的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:57:45