如何正确在自定义JS函数中添加setInterval/setTimeout实现定时输出
问题描述
需要实现alphabet函数,实现效果为每秒按顺序向控制台打印一个从指定起始字母到结束字母的字符(示例范围为a到f)。不加入定时逻辑时,基础的字母范围生成逻辑可以正常运行,但加入setInterval/setTimeout后执行结果不符合预期,原有存在问题的代码如下:
// setInterval(alphabet, 1000, 'a', 'f'); function alphabet(from, to) { var a = [], i = from.charCodeAt(0), j = to.charCodeAt(0); for (; i <= j; ++i) { setInterval(() => { a.push(String.fromCharCode(i)); }, 1000); } // return console.log(a); return a; } console.log(alphabet('a', 'f'));
问题根因
原有代码的问题主要有4点:
for循环属于同步逻辑,会在代码执行的瞬间跑完所有循环,一次性注册完全部定时任务,不会等待上一个定时任务触发后再执行下一轮循环- 循环内给每个字符都注册了
setInterval重复定时器,这类定时器会无限重复触发,1秒后所有注册的定时器会同时执行,完全做不到间隔1秒依次打印的效果 - 定时器回调是闭包,捕获的循环变量
i在回调真正触发时,已经是循环结束后的最终值,无法对应每一轮循环的目标字符 - 函数本身是同步返回的,在所有定时任务还没来得及执行的时候,就已经把空数组
a返回了,所以直接打印函数返回值只能拿到空数组
可行实现方案
方案1:setTimeout递归实现(推荐)
每次打印完当前字符后,再注册下一次1秒后的定时任务,天然保证打印间隔,到结束字符自动停止,不会有定时器残留问题。
function alphabet(from, to) { const startCode = from.charCodeAt(0); const endCode = to.charCodeAt(0); let currentCode = startCode; // 单步打印逻辑 function printNext() { const currentChar = String.fromCharCode(currentCode); console.log(currentChar); currentCode++; // 未到结束范围时,1秒后打印下一个 if (currentCode <= endCode) { setTimeout(printNext, 1000); } } // 启动打印 printNext(); } // 测试调用 alphabet('a', 'f');
方案2:setInterval+手动清除定时器
通过计数器记录当前打印位置,打印到最后一个字符时主动清除定时器,避免无限执行。
function alphabet(from, to) { const startCode = from.charCodeAt(0); const endCode = to.charCodeAt(0); let currentCode = startCode; const timer = setInterval(() => { const currentChar = String.fromCharCode(currentCode); console.log(currentChar); currentCode++; // 打印完全部字符后清除定时器 if (currentCode > endCode) { clearInterval(timer); } }, 1000); } // 测试调用 alphabet('a', 'f');
注意:使用
setInterval实现时必须手动清除定时器,否则定时器会在打印完全部字符后持续空转,造成不必要的性能消耗。
内容的提问来源于stack exchange,提问作者artmeister
相关产品推荐
相关产品推荐

