为何setInterval需等待for循环结束才执行?游戏循环问题
问题:循环执行顺序不符合预期
期望流程:完成一轮三轮问答(收集汽车品牌、每秒提速值、最大速度)→ 调用setInterval执行加速逻辑 → 定时器结束后重复此流程3次。
实际问题:程序会先连续完成3轮问答,之后才执行所有setInterval的逻辑。
原代码
//require "prompt-sync" const prompt = require("prompt-sync")({ sigint: true }); //Auto class class Car{ constructor(brand, speed, maxSpeed, currentSpeed){ this.carBrand = brand; this.carSpeed = speed; this.carMaxSpeed = maxSpeed; this.carCurrentSpeed = currentSpeed; } drive(){ if(this.carCurrentSpeed >= this.carMaxSpeed){ clearInterval(inter); console.log("too fast"); }else{ this.carCurrentSpeed = this.carCurrentSpeed + this.carSpeed; console.log(this.carBrand + " has a speed of " + this.currentSpeed + " km/h"); } } } //gameloop for(var i = 0; i < 3; i++){ //infos from usr let brand = prompt("what brand is your car? "); let speed = parseInt(prompt("How much speed does your car gain per second? ")); let maxSpeed = parseInt(prompt("what is the maximum speed of your car? ")); //create Object var usrAuto = new Car(brand, speed, maxSpeed, 0); //setInterval var inter = setInterval(usrAuto.plus.bind(usrAuto), 1000); }
问题原因
prompt是同步阻塞方法,会直接卡住主线程直到用户输入完成,for循环会一次性执行完3轮问答逻辑。setInterval是异步任务,会被放到事件队列中,等主线程的同步代码全部执行完毕后才会开始执行。- 原代码存在两处语法错误:
setInterval中调用的usrAuto.plus方法不存在,应为类定义的drive方法drive方法中错误使用this.currentSpeed,实际应为this.carCurrentSpeed
解决方案
使用async/await结合Promise封装定时器的结束逻辑,让每轮流程等待加速完成后再进入下一轮:
const prompt = require("prompt-sync")({ sigint: true }); class Car { constructor(brand, speed, maxSpeed, currentSpeed) { this.carBrand = brand; this.carSpeed = speed; this.carMaxSpeed = maxSpeed; this.carCurrentSpeed = currentSpeed; } drive(intervalId) { if (this.carCurrentSpeed >= this.carMaxSpeed) { clearInterval(intervalId); console.log(`${this.carBrand} 已达到最大速度,停止加速`); // 触发Promise的resolve,通知本轮加速结束 this.onFinish(); } else { this.carCurrentSpeed += this.carSpeed; console.log(`${this.carBrand} 当前速度:${this.carCurrentSpeed} km/h`); } } // 将定时器逻辑封装为Promise,等待加速结束 startDriving() { return new Promise((resolve) => { this.onFinish = resolve; const intervalId = setInterval(() => this.drive(intervalId), 1000); }); } } // 异步游戏循环 async function gameLoop() { for (let i = 0; i < 3; i++) { console.log(`=== 第 ${i + 1} 轮 ===`); // 同步收集用户输入 const brand = prompt("你的汽车品牌是?"); const speed = parseInt(prompt("每秒提速多少km/h?")); const maxSpeed = parseInt(prompt("汽车的最大速度是多少?")); // 创建汽车实例 const usrAuto = new Car(brand, speed, maxSpeed, 0); // 等待本轮加速完成后再进入下一轮 await usrAuto.startDriving(); console.log(`=== 第 ${i + 1} 轮结束 ===\n`); } console.log("所有轮次完成!"); } // 启动游戏循环 gameLoop();
关键修改点
- 给
Car类新增startDriving方法,将定时器逻辑封装为Promise,当达到最大速度时触发resolve,标记本轮结束。 - 游戏循环改为
async函数,用await等待每轮的Promise完成,确保一轮流程彻底结束后再进入下一轮。 - 修复了原代码中的属性名错误和方法调用错误。
内容的提问来源于stack exchange,提问作者asgr
相关产品推荐
相关产品推荐

