为什么打字稿 'async' 方法在第一次 'await' 出现之前就像同步一样

Why typescript 'async' methods act like a sync till the first 'await' occurrence

为什么代码在同一个 'stack' 中只在第一次等待之前执行?

 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

这是 async-await 风格编程的预期行为。

在这个方法中:

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 returns 是一个承诺,但该承诺会被忽略并超出范围。

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

您遇到的情况在 JavaScript 和 TypeScript 中都会发生。在不是 Promise turns the expression into a resolved Promise.

的表达式之前放置 await

If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.

原版 JavaScript 使用 async/await:

以下代码段等同于您原来的 await 示例。 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();

等价于 JavaScript 使用 Promise:

下一个片段更详细地展示了正在发生的事情。我删除了 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();