如何编写更优的async/await与Promise代码?现有数据等待实现能否简化?
代码优化方案
最小改动简化(兼容原有调用逻辑)
原逻辑的冗余点:
- 通用属性名(
promise、promiseResolve)容易和业务对象的其他属性重名,引发冲突 - 数据加载完成后,每次调用
waitForData都会新建Promise.resolve(this.data)实例,产生不必要的开销 - 单独把
promiseResolve挂在this上,需要额外做存在性判断,逻辑分散
简化后的代码完全兼容原有调用习惯:
async function doAction() { await this.waitForData(); // 原有后续业务逻辑直接保留,仍然使用this.data即可 } function waitForData() { // 仅首次调用创建pending状态的Promise,后续直接复用同一个实例 if (!this.dataReadyPromise) { this.dataReadyPromise = new Promise(resolve => { // 直接绑定resolve到Promise实例上,不用额外挂在this下 this.dataReadyPromise.resolve = resolve; }); } return this.dataReadyPromise; } function loadData(data) { this.data = data; // 可选链简化判断,不需要手动校验resolve方法是否存在 this.dataReadyPromise?.resolve?.(data); }
封装式可复用版本(适合多场景复用)
如果数据等待、加载的逻辑需要在多处复用,可以把状态完全封装,避免散落在业务对象的this上:
class DataReadyHandler { constructor() { this.data = null; this._readyPromise = null; this._resolve = null; } // 等待数据就绪,未加载时保持pending,加载完成后直接返回结果 wait() { if (!this._readyPromise) { this._readyPromise = new Promise(res => this._resolve = res); } return this._readyPromise; } // 传入数据触发就绪 setData(data) { this.data = data; this._resolve?.(data); } }
业务侧调用方式:
// 初始化实例,绑定到业务对象上 this.dataHandler = new DataReadyHandler(); // doAction中等待数据 async function doAction() { await this.dataHandler.wait(); // 直接从实例取数据 const currentData = this.dataHandler.data; } // 数据加载完成后调用setData this.dataHandler.setData(接口返回的结果);
可扩展点:如果需要处理数据加载失败的场景,只需在类中增加reject逻辑即可,避免Promise一直pending导致后续调用永久卡住。
内容的提问来源于stack exchange,提问作者hames
相关产品推荐
相关产品推荐

