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

未使用async方法时,我的TypeScript代码为何没有同步运行?

问题核心原因

你遇到的执行顺序问题本质是 Node.js异步IO回调机制 导致的,你调用的node-mbus包的connect、getData、close方法全都是异步非阻塞方法,不会阻塞后续代码执行,等回调触发的时候你的同步return早就执行完了。

你代码里的具体问题点:

  • 你调用mbusmaster.getData时传入的回调函数,会等到MBus总线实际返回数据后才会触发,这一步是异步的,不会阻塞forEach循环继续执行,也不会阻塞后续的mbusmaster.close()和return returnValue语句。
  • 当你执行完readData方法的return语句拿到返回值时,所有getData的回调都还没触发,所以returnValue是空数组,长度自然是0,后面回调依次触发才会往数组里push数据,这就是你先看到0输出,后看到数组输出的原因。
  • 额外的隐藏问题:你在所有getData回调还没执行的时候就调用了mbusmaster.close(),很可能会导致还没收到的总线数据直接被中断,部分请求失败。
修复方案

你可以把readData方法改写成返回Promise<Counter[]>的异步方法,等待所有数据读取完成后再返回结果:

import MbusMaster, { SerialOptions } from "node-mbus";

// 此处保留你原有Counter类型定义即可
type Counter = {
  mbusAddress: number;
  relevantRecords: Array<{id: number, scaleFactor: number, value?: number}>;
  [key: string]: any;
}

export class MbusReader {
    private countersToRead: Counter[];
    constructor(countersToRead: Counter[]) {
        this.countersToRead = countersToRead;
    }

    // 修改返回值为Promise
    async readData(connectionOptions: SerialOptions): Promise<Counter[]> {
        return new Promise((resolve, reject) => {
            const mbusmaster = new MbusMaster(connectionOptions);
            const returnValue: Counter[] = [];
            // 记录需要处理的计数器总数
            const totalTasks = this.countersToRead.length;
            let completedTasks = 0;

            mbusmaster.connect((err) => {
                if (err) return reject(new Error(`连接MBus失败: ${err}`));
                
                this.countersToRead.forEach(counter => {
                    mbusmaster.getData(counter.mbusAddress,(err:string,data:any) => {
                        if (err) return reject(new Error(`读取地址${counter.mbusAddress}失败: ${err}`));
                        
                        const valuedCounter: Counter = { ...counter };
                        valuedCounter.relevantRecords.forEach((dr,index) => {
                            const value = data.DataRecord.filter((rec:any) => rec.id === dr.id)[0].Value;
                            valuedCounter.relevantRecords[index] = { 
                                ...valuedCounter.relevantRecords[index], 
                                value: value * dr.scaleFactor 
                            };
                        })
                        returnValue.push(valuedCounter);
                        completedTasks++;

                        // 所有任务完成后关闭连接并返回结果
                        if (completedTasks === totalTasks) {
                            mbusmaster.close();
                            resolve(returnValue);
                        }
                    })
                })
            });
        })
    }
}

调用时需要使用async/await语法等待异步结果返回:

// 调用逻辑需要包裹在async函数中
async function main() {
    const reader = new MbusReader(counters);
    const res = await reader.readData(options);
    console.log(res.length); // 此处将输出正确的数组长度
}
main().catch(console.error);

内容的提问来源于stack exchange,提问作者schgab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 17:24:03