JS使用setInterval导致堆溢出

问题描述

使用setInterval运行较长一段时间后出现堆溢出的情况。
在这里插入图片描述
在这里插入图片描述

代码类似于

setInterval(sendHeartbeat, 30000);function sendHeartbeat() {axios.get(url).then(res => {console.log("success")}).catch(err => {console.error(err.message);})
}

在一些老机器上运行较长时间就会出现堆溢出,在性能好一点的机器则不会。

猜测出现堆溢出的原因

1、sendHeartbeat方法中有递归调用。

2、sendHeartbeat函数执行时间较长,可能会导致大量的函数调用堆积在内存中,最终导致堆栈溢出。

很显然sendHeartbeat方法是没有递归的,那么只有可能是2的原因了。

解决方案

1、增加定时器的间隔

可以增加定时器的间隔,让方法里面的代码有足够的时间去执行。缺点是不能确定增加间隔之后会不会出现堆溢出。

2、使用setTimeout - 推荐

把上面的代码改造成下面的样子,可以看到我使用了两个setTimeout做成递归的形式替换了setInterval,这样sendHeartbeat方法就会一个个的执行,不会产生堆积。

// 最初的调度
setTimeout(sendHeartbeat, 30000);function sendHeartbeat() {axios.get(url).then(res => {console.log("success")}).catch(err => {console.error(err.message);}).finally(() => {// 调度下一次执行setTimeout(sendHeartbeat, 30000);})
}

3、使用定时任务

但是使用定时任务是不能避免任务堆积的问题的。

const cron = require('node-cron');// 定义定时任务,每30秒执行一次
cron.schedule('*/30 * * * * *', function() {sendHeartbeat();
});function sendHeartbeat() {axios.get(url).then(res => {console.log("success")}).catch(err => {console.error(err.message);})
}

改进版-状态标记

let running = false; // 用于标记任务是否正在运行// 定义定时任务,每30秒执行一次
cron.schedule('*/30 * * * * *', function() {if (!running) { // 如果任务不在运行中,执行任务running = true; // 标记任务为运行中sendHeartbeat().then(() => {running = false; // 标记任务为未运行}).catch(err => {console.error(err.message);running = false; // 标记任务为未运行});}
});async function sendHeartbeat() {await axios.get(url).then(res => {console.log("success")}).catch(err => {console.error(err.message);})
}

总结:

使用setTimeout的优势在于它会等待函数执行完成后再次调用,而不会像setInterval那样按照固定时间间隔调用函数。这使得您可以更好地控制函数之间的间隔,避免函数重叠执行,从而减少了堆积和内存问题的风险。

当函数执行时间不确定或可能较长时,使用setTimeout可以更灵活地调度下一次执行,而不会导致内存问题。此外,使用setTimeout还可以避免setInterval可能出现的时间累积偏差问题。

然而,选择解决方案通常取决于具体的应用场景和需求。如果您需要更复杂的定时任务调度和精确的执行时间,那么使用定时任务(比如node-cron)也是一个不错的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/125779.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

golang gin框架1——简单案例以及api版本控制

gin框架 gin是golang的一个后台WEB框架 简单案例 package mainimport ("github.com/gin-gonic/gin""net/http" )func main() {r : gin.Default()r.GET("/ping", func(c *gin.Context) {//以json形式输出,还可以xml protobufc.JSON…

IPT2602协议-USB 快速充电端口控制器

产品描述: IPT2602是一款USB端口快速充电协议控制芯片。IPT2602智能识别多种快速充电协议,对手机等受电设备进行快速充电。IPT2602根据受电设备发送的电压请求能够精确的调整VBUS输出电压,从而实现快速充电。 IPT2602在调整5V输出电压前会自动…

关掉在vscode使用copilot时的提示音

1. 按照图示的操作File --> Preferences --> Settings 2. 搜索框输入关键字Sound,因为是要关掉声音,所以找有关声音的设置 3. 找到如下图所示的选项 Audio Cues:Line Has Inline Suggetion,将其设置为Off 这样,就可以关掉suggest code时…

Vue中如何进行分布式搜索与全文搜索(如Elasticsearch)

在Vue中实现分布式搜索与全文搜索(使用Elasticsearch) 分布式搜索和全文搜索在现代应用程序中变得越来越重要,因为它们可以帮助用户快速查找和检索大量数据。Elasticsearch是一种强大的分布式搜索引擎,它可以用于实现高性能的全文…

pytorch的pixel_shuffle转tflite文件

torch.pixel_shuffle()是pytorch里面上采样比较常用的方法,但是和tensoflow的depth_to_space不是完全一样的,虽然看起来功能很像,但是细微是有差异的 def tf_pixelshuffle(input, upscale_factor):temp []depth upscale_factor *upscale_f…

ROS2 库包设置和使用 Catch2 进行单元测试

说明 本文的目的是了解如何在 ROS2 中创建库,以供其他 ROS2 包使用。除此之外,本文还介绍了如何使用 catch2 框架编写单元测试。本文的第 1 部分将详细介绍如何创建库包。第 2 部分将介绍 ROS2 软件包如何利用创建的库 上篇 ROS2 库包设置和使用 Catch2…

操作系统知识

操作系统基础 什么是操作系统? 通过以下四点可以概括操作系统到底是什么: 操作系统(Operating System,简称 OS)是管理计算机硬件与软件资源的程序,是计算机的基石。操作系统本质上是一个运行在计算机上的…

矢量图形编辑软件illustrator 2023 mac特点介绍

illustrator 2023 mac是一款矢量图形编辑软件,用于创建和编辑排版、图标、标志、插图和其他类型的矢量图形。 illustrator mac软件特点 矢量图形:illustrator创建的图形是矢量图形,可以无限放大而不失真,这与像素图形编辑软件&am…

基于虚拟阻抗的下垂控制——孤岛双机并联Simulink仿真

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

LLM评估标准有哪些?

为了有效衡量和优化LLM的性能和泛化能力,并揭示其优势和局限,建立合理的LLM评价基准具有重要意义。现阶段,主流的LLM评估方法可划分为3类: 1)人工评估。 基于人工的评估方法通常需要邀请大量的志愿者或相关领域专家对…

【图像处理GIU】图像分割(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

国庆特别篇:中秋与国庆同日相迎

国庆特别篇:中秋与国庆同日相迎 国庆特别篇:中秋与国庆同日相迎 🎉摘要引言旅途风景分享 🗺️中秋团圆,返乡之路风景宜人的旅游胜地 技术探讨:Java中的可变参数 🚀什么是可变参数?使…