You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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);
}

问题原因

  1. prompt是同步阻塞方法,会直接卡住主线程直到用户输入完成,for循环会一次性执行完3轮问答逻辑。
  2. setInterval是异步任务,会被放到事件队列中,等主线程的同步代码全部执行完毕后才会开始执行。
  3. 原代码存在两处语法错误:
    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:24:31