如何让async/await写法的代码实现Promise的串行执行效果?
问题:如何修改TestAsync类使其与TestPromise类行为一致?
我正尝试将返回Promise的代码转换为async/await写法,现有两个TypeScript类:
TestAsync类(当前行为不符合预期)
该类的函数标记为async,但执行时先打印“Async 2: 2”再打印“Async 1: 1”,属于并行执行,未等待前一个函数完成:
class TestAsync { private async f1(n: any) { setTimeout(() => { console.log("Async 1: " + n); return n; }, 1500); } private async f2(n: any) { setTimeout(() => { console.log("Async 2: " + n); return n; }, 1000); } public async f() { await this.f1(1) await this.f2(2); } }
TestPromise类(行为符合预期)
该类直接返回Promise,执行时先打印“Promise 1: 1”再打印“Promise 2: 2”,符合串行执行的预期:
class TestPromise { private f1(n: any) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(n); console.log("Promise 1: " + n); }, 1500); }); } private f2(n: any) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(n); console.log("Promise 2: " + n); }, 1000); }); } public async f() { await this.f1(1); await this.f2(2); } }
问题原因
TestAsync类的核心问题是:async修饰的函数内部,setTimeout没有被包裹在Promise中。async函数默认会返回一个已resolved的Promise,但内部的setTimeout是独立的异步操作,不会被async函数自动等待。因此await this.f1(1)会立即完成,转而执行this.f2(2),导致两个定时器并行触发,最终先打印耗时更短的"Async 2: 2"。
修改方案
需要将setTimeout包装成Promise,让async函数真正等待异步操作完成后再返回。修改后的TestAsync类如下:
class TestAsync { private async f1(n: any) { // 将setTimeout包装为Promise return new Promise((resolve) => { setTimeout(() => { console.log("Async 1: " + n); resolve(n); }, 1500); }); } private async f2(n: any) { return new Promise((resolve) => { setTimeout(() => { console.log("Async 2: " + n); resolve(n); }, 1000); }); } public async f() { await this.f1(1); await this.f2(2); } }
说明
修改后,f1和f2内部的异步操作会通过Promise的resolve通知async函数完成时机,await this.f1(1)会等待1500ms的定时器完成后,再执行await this.f2(2),最终会先打印"Async 1: 1",再打印"Async 2: 2",与TestPromise类的行为完全一致。
内容的提问来源于stack exchange,提问作者ctulu
相关产品推荐
相关产品推荐

