未使用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
相关产品推荐
相关产品推荐

