为什么在第一次出现“ await”之前,打字稿“ async”方法就像一个同步器

时间:2019-05-12 18:56:23

标签: typescript async-await es6-promise

为什么只有在第一次等待之前,代码才在同一“堆栈”中执行?

 class SomeSyncClass {

  async method(): Promise<void> { 
     console.log('in start async');

     await this.someotherMethod();

    console.log('in finish async');
  }

  someotherMethod(): void { }


  method2(): void {
    console.log('before');
    this.method();
    console.log('after');
  }
}

new SomeSyncClass().method2(); 

输出:

before 
in start async
after
in finish async

但是,如果我删除了await-它将被同步执行:

 class SomeSyncClass {

  async method(): Promise<void> { 
     console.log('in start async');

     this.someotherMethod();

    console.log('in finish async');
  }

  someotherMethod(): void { }


 method2(): void {
   console.log('before');
   this.method();
   console.log('after');
}
}

new SomeSyncClass().method2(); 

输出:

before
in start async
in finish async
after

2 个答案:

答案 0 :(得分:1)

这是异步等待样式编程的预期行为。

在这种方法中:

async method(): Promise<void> { 
  console.log('in start async');
  await this.someotherMethod();
  console.log('in finish async');
}

由于中间有await调用,因此第二条日志语句无法与第一条日志相同地执行。本质上,它被编译成这样:

async method(): Promise<void> { 
  console.log('in start async');
  this.someotherMethod().then(result => {
    console.log('in finish async');    
  })
}

正如您所见,只有在someotherMethod被解析之后,才会调用第二条日志语句。

但是,由于async-await规则,第二个变体根本没有转换。尽管someotherMethod返回了一个诺言,但该诺言只是被忽略并超出了范围。

这些规则与Typescript无关,直接嵌入到JavaScript运行时和ECMA规范中。

答案 1 :(得分:1)

您遇到的事情同时在JavaScript和TypeScript中发生。将await放在不是Promise turns the expression into a resolved Promise.的表达式之前

  

如果await运算符后面的表达式的值不是Promise,则将其转换为解析的Promise。

使用async/await的Vanilla JavaScript:

以下代码段等效于您的原始await示例。等待使同步func3()表现得好像是异步的,因为它已转换为解析的Promise

const func3 = () => {}

const func2 = async() => {
  console.log('in start async');
  // The await wraps the synchronous func3 in a resolved Promise.
  await func3();
  console.log('in finish async');
}

const func1 = () => {
  console.log('before');
  func2();
  console.log('after');
}

func1();

使用Promise的等效JavaScript:

下一个代码片段将更详细地显示正在发生的事情。我删除了await并手动将func3()包装到已解决的Promise中。这可能会澄清正在发生的事情。

const func3 = () => {}

const func2 = () => {
  console.log('in start async');

  // This is the equivalent of await func3(); console.log('...');
  Promise.resolve(func3()).then(() => {
    console.log('in finish async');
  });
}

const func1 = () => {
  console.log('before');
  func2();
  console.log('after');
}

func1();