如何在Node.js中实现定时递归函数且不触发RangeError栈溢出
问题原因
- 核心错误是
setTimeout(timeDisplay() , {}, refresh)的写法不符合规范:timeDisplay()带括号会立即执行该函数,而不是将函数作为回调交给setTimeout延迟1秒触发。 - 这一错误会导致程序进入无等待的无限递归调用链路:
timeDisplay()执行完直接调用timeClock(),timeClock()又立刻执行timeDisplay(),完全没有1秒延迟,所以打印的时间都是相同的,且调用栈会快速耗尽,最终抛出RangeError: Maximum call stack size exceeded错误。 - 你提到的前端环境能正常运行并不符合实际逻辑,大概率是你移植代码的时候出现了笔误,原生JS前端环境运行这段代码同样会触发栈溢出错误,只是浏览器的调用栈上限比Node.js略高,看起来能多运行几秒而已。
解决方案
将setTimeout的第一个参数改为函数引用即可,不需要加执行括号,同时可以删掉无用的第二个空对象参数:
把原代码中的mytime = setTimeout(timeDisplay() , {}, refresh)修改为mytime = setTimeout(timeDisplay, refresh)
修正后的完整可运行代码
function addZeroes(num) { if (num < 10) { var new_num = "0" + num } else { var new_num = num } return new_num } function timeClock(){ var refresh=1000; // 刷新间隔单位为毫秒 mytime = setTimeout(timeDisplay, refresh) } function timeDisplay() { rightNow = new Date(); minute = rightNow.getMinutes(); hour = rightNow.getHours(); seconds = rightNow.getSeconds(); theTime = "" theTime += addZeroes(hour) + ":" + addZeroes(minute) + ":" + addZeroes(seconds); console.log(theTime) timeClock() } timeDisplay()
可选优化方案
你也可以直接用setInterval实现固定间隔执行,无需每次递归调用setTimeout,代码更简洁:
function addZeroes(num) { return num < 10 ? "0" + num : num } function printTime() { const rightNow = new Date() const theTime = `${addZeroes(rightNow.getHours())}:${addZeroes(rightNow.getMinutes())}:${addZeroes(rightNow.getSeconds())}` console.log(theTime) } // 立即打印一次当前时间,之后每1秒打印一次 printTime() setInterval(printTime, 1000)
内容的提问来源于stack exchange,提问作者Nerd
相关产品推荐
相关产品推荐

