为什么只有在第一次等待之前,代码才在同一“堆栈”中执行?
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
答案 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();