我正在寻找有关如何优雅地处理异步数据检索的意见/解决方案。
在异步初始化带有某些数据的任何类时,我一直采用这种方法:
class SomeClass {
// Turning off ts compiler's strictPropertyInitialization
private someProperty: SomeType
public async init(): Promise<this> {
this.someProperty = await goAndGetDataFromWhoKnowsWhere();
return this;
}
public async aMethod(): Promise<AType> {
// do its thing
}
public async anotherMethod(): Promise<AnotherType> {
// do its thing
}
}
并希望用户(我自己/另一个同事)像这样使用此类:
const someResult = new SomeClass()
.init()
.then( thatClass => thatClass.aMethod() )
此方法肯定可以达到目的,但没有硬性限制可确保调用init()
。有时,当有人忘记它时,事情就会破裂。
我们可能可以打开strictPropertyInitialization
并在每个类方法中注入检查。这肯定可以工作,但是方法中的相同之处大喊着可能是更好的方法。
class SomeClass {
private someProperty: SomeType | undefined // To enforce null-checking
public async init(): Promise<this> {
this.someProperty = await goAndGetDataFromWhoKnowsWhere();
return this;
}
public async aMethod(): Promise<AType> {
if (!this.someProperty) await this.init();
// do its thing
}
public async anotherMethod(): Promise<AnotherType> {
if (!this.someProperty) await this.init();
// do its thing
}
}
这个问题有解决方案吗?有解决此问题的设计模式吗?帮助赞赏! :)
答案 0 :(得分:1)
您是否考虑过完全不公开new()
构造函数调用?如果您使构造函数private
,并公开一个静态init()
方法来异步构造一个实例并用数据填充它,该怎么办:
class SomeClass {
static async init(): Promise<SomeClass> {
return new SomeClass(await goAndGetDataFromWhoKnowsWhere());
}
private constructor(private someProperty: SomeType) { }
// your other methods
}
new SomeClass("oops"); // can't do this
SomeClass.init().then(thatClass => thatClass.aMethod());
现在,任何人都不可能以错误的方式使用此方法。希望能给您一些想法。祝你好运!
答案 1 :(得分:0)
另一个选择是您可以将类的创建包装在函数中。假设必须在每个实例上调用init
,则可以在创建时处理它:
(对不起,它不在TypeScript中;我只是不太熟悉。)
const goAndGetDataFromWhoKnowsWhere = async () => 123;
const SomeClass = () => {
class SomeClass {
async init() {
this.someProperty = await goAndGetDataFromWhoKnowsWhere();
return this;
}
}
return new SomeClass().init();
};
SomeClass().then(inst => {
console.log('someProperty:', inst.someProperty);
});
类似于jcalz's answer,这将不允许与new
关键字一起使用:
new SomeClass(); // TypeError: SomeClass is not a constructor
答案 2 :(得分:0)
只使用一个函数怎么样?
function SomeClass(){
var newObj = Object.create(/* your prototype */)
return goAndGetDataFromWhoKnowsWhere()
.then((data) => {
newObj.someProperty = data;
return newObj;
})
}
SomeClass().then((newObj) => {})