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

ASP.NET MVC项目运行几分钟后页面卡顿,强制刷新仅可临时恢复

问题排查与修复方案

核心卡顿根因

  • DOM节点泄漏:DisplayCheck每秒执行一次接口请求,placeCheck仅处理新节点的插入更新,没有清理已失效的旧DOM节点,运行时间越长页面累积的冗余DOM越多。配合refreshCheckTimers里的全局jQuery选择器遍历,性能消耗会随运行时间指数级上升,是卡顿的核心原因。
  • 重复DOM查询冗余:refreshCheckTimers中对同一个[data-uniqueID=xxx]元素执行了4次find查询,没有缓存查询结果,每次都需要遍历全量DOM树,放大了DOM过多带来的性能问题。
  • 定时器叠加风险:没有做定时器防重复逻辑,若DisplayCheck被多次触发会生成多个并行的定时任务,导致每秒实际执行的请求和渲染次数远大于1次,进一步加重性能负担。

具体修复代码

1. 修复DOM泄漏

在插入新节点前先移除同ID的旧节点,拉取全量数据后清理不在返回结果中的历史节点:

function placeCheck(check) {
    var currCheckID = $(check).attr("id");
    // 先移除已有同ID旧节点
    $(`[data-check-id='${currCheckID}']`).remove();

    // 原有后续逻辑保持不变
    var checkElement = jQuery.parseHTML(check);
    checkElement = styleCheck(checkElement);  
    var checkContent = $(checkElement[1]).html();
    var modalOpen = $(`body [data-check-id='${currCheckID}']`).length;
    populateExpandedCheck(checkContent, currCheckID);
    var expandedScrollPos = $(`body [data-check-id='${currCheckID}']`).attr("scrollPos");
    expandedScrollPos = (typeof expandedScrollPos === 'undefined') ? 0 : expandedScrollPos;
    $(`body [data-check-id='${currCheckID}']`).find(".check-mainbody").scrollTop(expandedScrollPos);
}

2. 优化DOM查询性能

缓存重复查询的DOM元素,减少遍历次数:

function refreshCheckTimers() {
    $(".check-timer").each(function () {
        const $timer = $(this);
        const dish_id = $timer.attr("data-longestDish");
        const $mainbody = $timer.closest(".check-footer").siblings(".check-mainbody");
        // 仅查询一次目标菜品节点,后续复用缓存结果
        const $targetDish = $mainbody.find(`[data-uniqueID=${dish_id}]`);
        
        const prepTime = parseInt($targetDish.attr("data-prepTime"));
        const dish_status = parseInt($targetDish.attr("data-status"));
        let activeCourse = $targetDish.attr("data-course");
        if (activeCourse == "mains" || activeCourse == "sides") {
            activeCourse = "MCSI";
        }
        // 后续逻辑全部复用$targetDish、$mainbody等缓存变量即可
        ...
    })
}

3. 避免定时器叠加

全局存储定时器ID,确保同一时间只有一个定时任务运行:

// 全局存储定时器ID
let displayTimer = null;
function DisplayCheck() {
    // 先清除已有的旧定时器,避免并行执行
    if(displayTimer) clearTimeout(displayTimer);
           
    const TableNumber = $(".table-entry").val();
    const checkDate = new Date().toISOString();
    
    $.ajax({
        type: "POST",
        cache: false,
        url: '@Url.Action("DisplayCheckForTable", "KitchenScreens")',
        contentType: "application/json;",
        data: JSON.stringify({ TableNumber: TableNumber }),
        success: function (result) {
            for (const c in result.lstChecks) {
                placeCheck(result.lstChecks[c]);
            }
        },
        complete: function () {
            displayTimer = setTimeout(DisplayCheck, 1000);
        },
        error: function (xhr, status, error) {
            console.warn(xhr.responseText);
        }
    });
}

可选优化项

  • 将请求间隔从1秒调整为2-3秒,厨房展示场景对实时性要求不高,可大幅降低请求和渲染压力
  • 新增数据diff逻辑,仅当后端返回数据和前端现有数据有差异时才执行DOM更新,避免每秒重复渲染相同内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 16:30:03