【问题标题】:Promise to async/await承诺异步/等待
【发布时间】:2017-06-15 16:57:47
【问题描述】:

我有以下代码。

class DB {
  constructor(client) {
    this.client = client;
  }
}

export default function store() {
  return new Promise((resolve, reject) => {
    pg.connect(process.env.DATABASE_URL, client => {
      client.query('CREATE TABLE x(name VARCHAR(100))');
      return resolve(new DB(client));
    });
  });
}

有没有办法在类构造函数中移动 store 函数并使用 async/await 重写它?

【问题讨论】:

  • 您是否已经尝试过?请向我们展示您的代码。我们可以从那开始讨论...
  • 我不认为这是可能的;构造函数本质上是同步的,所以你不能在构造函数内部进行异步操作(至少不能正确)。
  • 同意@Frxstrem。通常构造函数应该返回你的新实例。您可以将 store 函数添加到您的类并在构造函数中触发它(将 promise 分配给实例属性)。
  • async 关键字返回一个 Promise,因此它与使用 Promise 没有什么不同,只是您使用 await 获得了一个不错的语法糖
  • 您要解决的问题是什么?

标签: javascript async-await ecmascript-2017


【解决方案1】:

您无法完全避免 Promise 构造函数,因为您需要它来承诺连接:

function connect(url) {
  return new Promise((resolve, reject) => {
    pg.connect(url, resolve);
  });
}

这样,你就可以使用async/await

export default async function store() {
  const client = await connect(process.env.DATABASE_URL);
  client.query('CREATE TABLE x(name VARCHAR(100))');
  return new DB(client);
}

如果你愿意,你可以将该函数移到你的类中,但我看不出有任何理由:

export default class DB {
  constructor(client) {
    this.client = client;
  }
  static async store() {
    const client = await connect(process.env.DATABASE_URL);
    client.query('CREATE TABLE x(name VARCHAR(100))');
    return new this(client);
  }
}

【讨论】:

    【解决方案2】:

    AFAIK 你不能将构造函数声明为异步函数。但是,您可以从构造函数返回一个 Promise。 This seems to be a terrible idea, so don't use this in a real-world context.

    // Define the class
    class DB {
      constructor() {
        return this.store().then(client => { this.client = client; return this; });
      }
    
      async store() {
        const client = await new Promise((resolve) => {
          pg.connect(process.env.DATABASE_URL, resolve);
        });
        client.query('CREATE TABLE x(name VARCHAR(100))');
        return new DB(client);
      }
    }
    
    // Create an async function environment
    (async function handleData() {
      const db = await new DB();
      // Do something with your DB
    })();
    

    【讨论】:

    • 这不会像你期望的那样工作。构造函数总是返回一个实例。构造函数中的return 被忽略。
    • Jup,我怀疑了一下(因为没有承诺,结果会一样)。改用实例属性试试:class A { constructor() { this.name = 12; return Promise.resolve(this.name); } } (async () => { const a = await new A(); console.log(a); })();
    • 除非我完全误解正在发生的事情,否则这似乎按预期工作。还是我完全不在基地?
    • 哇,我完全没想到。很抱歉草率下结论。我用new (class { constructor() { return "foo"; } })() 测试了我的断言,它返回一个匿名类的实例而不是"foo",但现在我看到这种行为只适用于原语;如果return 值是一个对象,则构造函数将返回该对象,就像在您的代码中一样。我将不得不去规范,看看是什么,呃,指定。附言我不知道谁对你的答案投了反对票,但不是我。我只是赞成它。 ;)
    • Don't return a promise from new DB()。带有静态 store 函数的 OP 模式非常好,应该是这样构造的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2018-03-05
    • 1970-01-01
    • 2020-03-26
    • 2018-12-24
    • 2023-04-06
    相关资源
    最近更新 更多