TypeScript中如何在getter访问器内调用异步函数
问题核心原因
- JavaScript/TypeScript的getter是同步执行语法,不支持声明为async,即使在getter内调用async方法,也不会等待异步返回就会继续执行后续逻辑。你当前的写法第一次触发score计算时,
this.isScoreInverted永远是初始值false,等API返回结果时计算已经完成。 - 原有代码的
@computedFrom仅监听probabilityIndex和impactIndex两个字段,后续异步请求返回修改isScoreInverted时,不会触发score重新计算,会导致展示的分值和实际配置不匹配。 - 把API调用放在getter内,每次访问score都会触发一次接口请求,会产生大量无效请求,存在明显性能问题。
推荐实现方式
不要在getter内处理异步逻辑,把异步状态加载提前,同时把异步获取到的状态加入计算属性的依赖列表。
基础改造版(适配原有逻辑)
改造后代码如下:
export class TopModel{ private isScoreInverted: boolean = false; // 将isScoreInverted加入计算依赖,状态变更时自动重算score @computedFrom("probabilityIndex", "impactIndex", "isScoreInverted") public get score(): number | undefined { if (this.isScoreInverted) { return Service.calculateInvertedScore(); } else { return Service.calculateScore(); } } constructor( data?) { if (data) { Object.assign(this, data); } // 实例初始化时就拉取区域配置状态 this.loadRiskScoreInvertedStatus(); } private async loadRiskScoreInvertedStatus() { try { this.isScoreInverted = await this.matrixApi.getScoresInverted(); } catch (err) { // 接口请求失败时走默认非倒置逻辑,可按需调整兜底逻辑 this.isScoreInverted = false; } } }
这个版本的逻辑说明:
- 实例初始化时就触发接口请求拉取区域的分数倒置配置,不会重复调用接口
- 接口返回前score会先按默认非倒置逻辑计算一次,返回后因为
isScoreInverted变化自动触发score重算,视图会同步更新 - 如果需要等配置加载完成再展示分数,可以额外加一个
isConfigLoading的标记位,在模板里控制加载态即可
动态适配版(区域变更自动更新配置)
如果当前所在区域是动态变化的,不需要手动触发配置加载,可以监听区域字段的变化自动拉取最新配置:
export class TopModel{ private isScoreInverted: boolean = false; // 类上存储的当前区域标识字段 currentArea: string; @computedFrom("probabilityIndex", "impactIndex", "isScoreInverted") public get score(): number | undefined { return this.isScoreInverted ? Service.calculateInvertedScore() : Service.calculateScore(); } constructor( data?) { if (data) { Object.assign(this, data); } } // 监听区域字段变化,自动拉取对应区域的分数配置 @observable currentAreaChanged() { this.loadRiskScoreInvertedStatus(); } private async loadRiskScoreInvertedStatus() { try { this.isScoreInverted = await this.matrixApi.getScoresInverted(); } catch (err) { this.isScoreInverted = false; } } }
注意事项
- 不要在同步getter内放置无缓存的异步逻辑,很容易出现状态不一致、重复请求的问题
- 所有参与计算属性求值的可变字段,都要加入
@computedFrom的依赖列表,否则字段变更后不会触发计算属性更新 - 异步接口一定要加错误兜底,避免接口异常时页面状态一直停留在初始加载态
内容的提问来源于stack exchange,提问作者1klambo
相关产品推荐
相关产品推荐

