【问题标题】:How to execute asynchronous functions in the constructor? [duplicate]如何在构造函数中执行异步函数? [复制]
【发布时间】:2020-05-06 21:22:21
【问题描述】:

我正在尝试在 NodeJs 中实现 Customer 对象,并且该实例能够收集其数据。

class CustomerModel extends Model {
  public customer

  constructor(email:string) {
    super();
    this.collection = 'customer';
    this.customer = await CustomerLayer.getCustomerByEmail(email);
  }
}

但我不能有一个异步构造函数。我已经看到在 Javascript 中您可以执行以下操作:

const sleep = () => new Promise(resolve => setTimeout(resolve, 5000));
    class Example {
      constructor () {
        return new Promise(async (resolve, reject) => {
          try {
            await sleep(1000);
            this.value = 23;
          } catch (ex) {
            return reject(ex);
          }
          resolve(this);
        });
      }
    }

    (async () => {
      // It works as expected, as long as you use the await keyword.
      const example = await new Example();

      console.log(example instanceof Example);
      console.log(example.value);
    })();

但我认为从构造函数返回数据是不正确的。 从构造函数调用异步方法有什么正确的方法吗?

【问题讨论】:

标签: javascript node.js mongodb typescript


【解决方案1】:

我不会在构造函数中这样做。可能init 方法更适合这个用例。

class CustomerModel extends Model {
  public customer

  constructor(email:string) {
    super();
    this.collection = 'customer';
  }
  async init() {
   this.customer = await CustomerLayer.getCustomerByEmail(email);
  }
}
const myClass = new CustomerModel();
await myClass.init();

您还可以考虑创建一个静态方法来返回内部创建对象和初始化的实例。

【讨论】:

    【解决方案2】:

    这是不可能的。你有几个选择:

    • 您可以从构造函数显式返回一个 Promise(通过 new Promise 构造它)。这就是您在第二个代码中所做的。 await 总是可以替换为 Promise 构造函数和 .then。但是,这很奇怪,因为人们总是期望new Example() 的结果是instanceof Example - 一个不会期望new Example() 会导致一个承诺。这是您使用此方法的第一个代码的样子:
    class CustomerModel extends Model {
      public customer
    
      constructor(email:string) {
        super();
        this.collection = 'customer';
        return CustomerLayer.getCustomerByEmail(email)
          .then((customerByEmailResolveValue) => {
            this.customerByEmailResolveValue = customerByEmailResolveValue;
            return this;
          });
      }
    }
    const customerProm = new CustomerModel('foo');
    customerProm.then((actualCustomerInstance) => {
      // use actualCustomerInstance
    });
    
    • 在构造函数中,将 Promise 分配给实例的属性。然后,当您需要使用该值时,请在属性上调用 .then
    class CustomerModel extends Model {
      public customer
      constructor(email:string) {
        super();
        this.collection = 'customer';
        this.customerProm = CustomerLayer.getCustomerByEmail(email);
      }
    }
    const customer = new CustomerModel('foo');
    customer.customerProm.then((result) => {
      // use result;
    });
    
    • 您还可以在创建实例之前检索值,然后将其传入:
    class CustomerModel extends Model {
      public customer
      constructor(email:string, customerByEmailResolveValue) {
        super();
        this.collection = 'customer';
        this.customer = customerByEmailResolveValue;
      }
    }
    CustomerLayer.getCustomerByEmail(email)
      .then((customerByEmailResolveValue) => {
        const customer = new CustomerModel('foo', customerByEmailResolveValue);
      });
    

    【讨论】:

      猜你喜欢
      • 2016-02-07
      • 2017-04-14
      • 2012-08-05
      • 2014-07-19
      • 2020-07-28
      • 2018-09-16
      • 2013-12-27
      • 1970-01-01
      • 2014-10-28
      相关资源
      最近更新 更多