如何在执行任何类方法之前注入条件检查

问题描述 投票:0回答:3

我正在寻找关于如何优雅地处理异步数据检索的一些意见/解决方案。

在异步初始化任何具有某些数据的类时,我一直采用这样的方法:

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
  }
}

这个问题有什么解决方案吗?任何可以解决这个问题的设计模式?帮助赞赏! :)

javascript typescript oop asynchronous
3个回答
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());

现在,任何人都不可能以错误的方式使用它。希望能给你一些想法。祝好运!


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

0
投票

那么只使用一个函数呢?

function SomeClass(){
  var newObj = Object.create(/* your prototype */)
  return goAndGetDataFromWhoKnowsWhere()
  .then((data) => {
    newObj.someProperty = data;
    return newObj;
  })
}

SomeClass().then((newObj) => {})
© www.soinside.com 2019 - 2024. All rights reserved.