【问题标题】:Why typescript 'async' methods act like a sync till the first 'await' occurrence为什么打字稿“异步”方法在第一次“等待”出现之前就像同步一样
【发布时间】:2019-09-29 19:58:22
【问题描述】:

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

 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

【问题讨论】:

  • 在第一个示例中,您必须await this.method(); 才能获得正确的结果。就像现在一样,它在到达await this.someotherMethod(); 时返回,其余部分在this.someotherMethod(); 完成后执行。

标签: typescript async-await es6-promise


【解决方案1】:

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

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

原版 JavaScript 使用 async/await:

以下 sn-p 等效于您原来的 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();

使用Promise的等效JavaScript:

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

【讨论】:

    【解决方案2】:

    这是异步等待风格编程的预期行为。

    在这个方法中:

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

    第二条日志语句不能和第一条在同一个tick中执行,因为中间有await调用。它基本上被编译成这样的:

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

    正如您所见,它仅在 someotherMethod 被解析后才调用第二条日志语句。

    然而,由于异步等待规则,第二个变体根本没有被转换。尽管someotherMethod 事件返回了一个promise,但该promise 会被忽略并超出范围。

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

    【讨论】:

      猜你喜欢
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-20
      • 2018-05-03
      • 1970-01-01
      • 2023-02-21
      • 2015-06-09
      相关资源
      最近更新 更多