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

点击触发setTimeout后CPU占用飙升的原因及替代方案咨询

问题:点击触发新闻更新脚本后CPU占用飙升的排查与优化

问题场景

一段用于更新网站新闻板块的脚本功能正常,但点击触发后CPU瞬间占用率达40%,排查后定位到setTimeout的问题,各浏览器均存在此情况。

原脚本代码

function read_chat_adm(id_news) {
  var currentFileSize = 0;

  function updateFileContent_adm() {
    $.ajax({
      url: 'read_news_adm.php?id_n=' + id_news,
      cache: false,

      success: function(data) {
        var fileSize = data.length;
        if (currentFileSize !== fileSize) {
          $('#news_adm_read').html(data);

          currentFileSize = fileSize;
        }
      },
      complete: function() {
        setTimeout(updateFileContent_adm(), 5000);
      }
    });
  }
  updateFileContent_adm();
}

调用方式

<div id="news_adm_read"></div>
<span onclick="read_chat_adm('1235659845');">Load News</span>

问题根源

核心错误是setTimeout的调用方式:你直接执行了updateFileContent_adm()并把返回值传给setTimeout,而非传入函数引用。这会导致函数无延迟递归调用,瞬间被无限执行,直接拉满CPU。正确写法应该是传入函数本身(不带括号),让setTimeout在指定延迟后再执行函数。

优化方案

1. 修复setTimeout调用错误

这是最关键的修复,把带括号的函数执行改为传入函数引用:

complete: function() {
  setTimeout(updateFileContent_adm, 5000); // 去掉括号,传入函数本身
}

2. 防止重复轮询与终止无效请求

如果用户多次点击"Load News",会启动多个轮询实例,加剧资源占用。添加标记控制轮询状态,同时终止未完成的旧请求:

function read_chat_adm(id_news) {
  var currentFileSize = 0;
  var timerId = null; // 存储定时器ID
  var xhr = null; // 存储AJAX请求实例

  function updateFileContent_adm() {
    // 终止未完成的旧请求
    if (xhr && xhr.readyState !== 4) {
      xhr.abort();
    }

    xhr = $.ajax({
      url: 'read_news_adm.php?id_n=' + id_news,
      cache: false,

      success: function(data) {
        var fileSize = data.length;
        if (currentFileSize !== fileSize) {
          $('#news_adm_read').html(data);
          currentFileSize = fileSize;
        }
      },
      complete: function() {
        timerId = setTimeout(updateFileContent_adm, 5000);
      }
    });
  }

  // 清除已有定时器,避免重复启动轮询
  if (timerId) {
    clearTimeout(timerId);
  }
  updateFileContent_adm();
}

3. 替换轮询为主动推送(可选)

如果新闻更新频繁,轮询会持续消耗资源。可以改用Server-Sent Events(SSE) 或WebSocket,由服务器主动推送更新,彻底避免客户端频繁发起请求:

  • SSE适合单向消息推送,实现简单,兼容大部分现代浏览器;
  • WebSocket支持双向通信,功能更强大,但实现复杂度稍高。

4. 优化DOM更新逻辑

不要每次都用html(data)替换整个板块,对比新旧内容后只更新变化部分,减少DOM操作开销:

success: function(data) {
  var $target = $('#news_adm_read');
  if ($target.html() !== data) {
    $target.html(data);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 00:10:15