如何在构造函数中执行异步函数?

时间:2020-01-20 20:38:54

标签: javascript node.js mongodb typescript

我正在尝试在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);
    })();

但是我认为从构造函数返回数据是不正确的。 有没有正确的方法可以从构造函数中调用异步方法?

2 个答案:

答案 0 :(得分:4)

我不会在构造函数中这样做。可能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();

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

答案 1 :(得分:1)

不可能。您在这里有一些选择:

  • 您可以从构造函数显式返回Promise(通过new Promise进行构造)。这就是您在第二个代码中所做的。 await始终可以用Promise构造函数和.then代替。但是,这很奇怪,因为人们总是希望new Example()的结果成为instanceof Example-一个不会期望{{ 1}}以产生一个承诺。使用此方法,这就是您的第一个代码:
new Example()
  • 在构造函数中,将Promise分配给实例的属性。然后,当您需要使用该值时,请在属性上调用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 });
.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;
});