为图表数据刷新逻辑添加JavaScript闭包解决定时任务中断问题
问题原因
- 语法错误:
trigger函数内的30000延迟参数错误写到了catch的入参位置,不属于setTimeout的配置项,导致该定时实际无延迟立即执行,且未设置后续触发逻辑,执行一次后就终止。 - 逻辑冗余:两段完全相同的拉取、渲染逻辑重复编写,大幅提升出错概率。
- 无循环触发机制:
trigger内部完成数据拉取渲染后,没有继续设置下一次的定时任务,逻辑自然中断。 - 内存泄漏隐患:重复创建匿名回调函数,且未清理旧的定时器、未销毁旧图表实例,长期运行会占用多余内存。
修复方案
最小改动版本(仅修复原有代码的错误,不调整结构)
fetch('log_chart.txt') .then(function (response) { return response.text(); }) .then(function (text) { let series = csvToSeries(text); renderChart(series); setTimeout(trigger, 30000); }) .catch(function (error) { console.log(error); }); function trigger() { fetch('log_chart.txt') .then(function (response) { return response.text(); }) .then(function (text) { let series = csvToSeries(text); renderChart(series); }) .catch(function (error) { console.log(error); }) // 无论请求成功失败都设置下一次触发,避免因单次请求报错中断逻辑 .finally(function() { setTimeout(trigger, 30000); }); }
优化版本(闭包封装解决内存泄漏问题,更易维护)
// 闭包封装逻辑,避免全局变量污染,保存定时器ID方便清理 const chartPoller = (function() { let timerId = null; const POLL_INTERVAL = 30000; // 抽离公共拉取渲染逻辑,仅需维护一份代码 async function fetchAndRender() { try { const response = await fetch('log_chart.txt'); const text = await response.text(); const series = csvToSeries(text); // 若使用第三方图表库,可在此处先销毁旧实例,进一步降低内存占用 // 示例(ECharts):myChart.dispose() renderChart(series); } catch (error) { console.error('拉取图表数据失败:', error); } finally { // 清理旧定时器避免重复触发,再设置下一次拉取 if (timerId) clearTimeout(timerId); timerId = setTimeout(fetchAndRender, POLL_INTERVAL); } } // 暴露启动/停止方法,方便外部控制轮询状态 return { start: fetchAndRender, stop: function() { if (timerId) clearTimeout(timerId); timerId = null; } } })(); // 启动轮询 chartPoller.start();
内容的提问来源于stack exchange,提问作者Kalaloom
相关产品推荐
相关产品推荐

