类中的奇怪异步/等待行为

时间:2017-04-17 12:48:27

标签: javascript node.js asynchronous async-await

节点7.9.0

这是情景:

class TestClass {
  constructor() {
    const x = await this.asyncFunc()
    console.log(x)
  }
  async asyncFunc() {
    return new Promise((accept) => {
      setTimeout(() => accept("done"), 1000)
    })
  }
}
new TestClass()

第3行的错误为Unexpected token this

好的,所以我把它包起来...... const x = await (this.asyncFunc())

现在我得到await is not defined

这让我觉得节点7.9.0不知道等待/同步,尽管http://node.green/告诉我它是受支持的,并且它的示例运行正常。

(function(){
(async function (){
  await Promise.resolve();
  var a1 = await new Promise(function(resolve) { setTimeout(resolve,800,"foo"); });
  var a2 = await new Promise(function(resolve) { setTimeout(resolve,800,"bar"); });
  if (a1 + a2 === "foobar") {
    console.log("passed")
  }
}());
})()

2 个答案:

答案 0 :(得分:1)

添加异步启动功能并使用它可以解决问题:

因此可以使用异步启动函数修复初始示例:

class TestClass {
  constructor() {
    this.start()
  }
  async start() {
    const x = await this.asyncFunc1()
    console.log(x)
  }
  async asyncFunc1() {
    return new Promise((accept) => {
      setTimeout(() => accept("done"), 1000)
    })
  }
}
new TestClass()

如果你想在asyncFunc1中进一步调用等待你需要使promise函数也异步...

class TestClass {
  constructor() {
    this.start()
  }
  async start() {
    const x = await this.asyncFunc1()
    console.log(x)
  }
  async asyncFunc1() {
    return new Promise(async (accept) => {
      const x = await this.asyncFunc2()
      accept(x)
    })
  }
  async asyncFunc2() {
    return new Promise((accept) => {
      accept("done")
    })
  }
}
new TestClass()

答案 1 :(得分:-1)

恕我直言,在构造函数中使用await是不明智的。构造函数应该是轻量级的。构造函数不应该失败。

MSDN about constructors

  

考虑提供简单的,理想的默认构造函数。一个简单的   构造函数具有非常少的参数和所有参数   是原始类型或枚举。

考虑使用静态工厂   方法而不是构造函数,如果所需的语义   操作不直接映射到新实例的构造,   或者如果遵循构造函数设计指南感觉不自然。

一个好的解决方案是创建一个静态异步工厂方法,它可以调用一个简单的私有构造函数并调用你的私有异步函数。

这样,人们可以通过调用静态异步工厂方法来创建类实例的唯一方法,因此您可以确定已经调用了asyncFunc。

好消息是:一切都没有诡计

我对JAVA并不熟悉,以下是在C#中,但我想你会明白这个想法

class TestClass
{
    public async Task<TestClass> CreateAsync()
    {
        TestClass instance = new TestClass(); // lightWeight
        Promise p = await instance.AsyncFunc();
        // do what you need to do with your Promise
        Console.Log(...)
        return instance;
    }

    // private constructor: only CreateAsync can call it:
    private TestClass()
    {
        // make it lightweight
    }

    public async Task<Promise> AsyncFunc()
    {
        return new Promise((accept) => 
        {
            setTimeout(() => accept("done"), 1000)
        });
    }
}

使用。

而不是

TestClass myObject = new TestClass();
你会这样做:

 TestClass myObject = await TestClass.Creat();

你的调用将是异步的,构造函数是轻量级的,你确定你的asyncFunc被调用并等待。