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
相关产品推荐
相关产品推荐

