如何终止JavaScript中使用sleep函数实现的循环?
实现可终止的循环输出功能
当前代码的问题在于:用for循环一次性创建了所有的sleep Promise,这些任务会被浏览器按计划依次执行,就算点击Stop也无法中断;重复点击Submit还会叠加多个循环,导致输出混乱。要实现中途停止和重新执行,可按以下方案修改:
核心思路
- 用全局终止标志控制循环是否继续
- 把同步for循环改成异步循环(async/await),让每次迭代都能检查终止状态
- 点击Submit时先终止当前运行的循环,再启动新循环
修改后的完整代码
JavaScript 部分
let submitBtn, stopBtn, firstStepInput, lastStepInput, output = 0, stopOutput = 0; // 新增终止标志和当前循环的Promise引用 let isStopped = false; let currentLoop = null; document.addEventListener("DOMContentLoaded", () => { submitBtn = document.querySelector('#submit'); stopBtn = document.querySelector('#stop'); firstStepInput = document.querySelector('#firstStep'); lastStepInput = document.querySelector('#lastStep'); output = document.querySelector('#output'); stopOutput = document.querySelector('#stopOutput'); submitBtn.addEventListener('click', getValueInputs); stopBtn.addEventListener('click', stopLoop); }) function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 改成async函数,用异步循环替代同步for const getValueInputs = async () => { // 先终止当前正在运行的循环 if (currentLoop) { isStopped = true; await currentLoop; // 等待当前循环完全停止 } // 重置状态 isStopped = false; let firstInputValue = +firstStepInput.value || 0; let lastInputValue = +lastStepInput.value || 100; let current = firstInputValue; // 用while循环实现异步迭代,每次都检查终止标志 currentLoop = (async () => { while (current <= lastInputValue && !isStopped) { output.innerHTML = current; await sleep(1000); // 原代码i*1000会导致间隔越来越长,这里改成固定1秒,可按需调整 current++; } // 循环结束后重置引用 currentLoop = null; })(); } const stopLoop = () => { isStopped = true; stopOutput.innerHTML = output.innerHTML; }
HTML 部分
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"/> <div> <div class="ms-3"> <div class="d-flex align-items-center mt-3"> <div> <label for="firstStep">firstStep</label> <input id="firstStep" type="number" class="form-control" /> </div> <span class="mx-3">to</span> <div> <label for="lastStep">lastStep</label> <input id="lastStep" type="number" class="form-control" /> </div> </div> <div class="mt-3 mx-auto"> <button id="submit" class="btn btn-sm btn-primary">Submit</button> <button id="stop" class="btn btn-sm btn-info">Stop</button> </div> <div class="mt-3"> <p id="output"></p> </div> <div class="mt-3"> <p id="stopOutput"></p> </div> </div> </div>
关键修改说明
- 终止标志
isStopped:每次循环迭代前都会检查这个标志,一旦设为true就立即退出循环 - 异步循环:用
async/await配合while循环,替代原来的同步for循环,确保每次延迟后都能响应终止指令 - 循环跟踪:用
currentLoop记录当前正在运行的循环Promise,点击新的Submit时先终止旧循环,避免多个循环同时运行 - Stop功能优化:点击Stop时不仅记录当前值,还会终止循环,停止后续输出
内容的提问来源于stack exchange,提问作者davood beheshti
相关产品推荐
相关产品推荐

