TypeScript如何优雅等待仅回调无Promise返回的外部服务完成
解决方案
核心思路是将回调风格的第三方服务封装为Promise版本,再通过Promise.all等待所有并行调用执行完成后再判断结果,完全不需要定时器轮询。
之前直接给getInfoFromService添加async关键字不生效的原因是,async/await仅能等待Promise对象的状态变更,原生回调式方法没有返回Promise,无法被await感知到执行进度。
具体修改步骤
- 第一步:封装回调式服务为Promise方法
对原有的fakeService做一层包装,把回调触发的结果通过Promise的resolve抛出,这样就可以用await等待执行完成。 - 第二步:改造
getInfoFromService为异步方法
收集所有并行调用的Promise实例,用Promise.all等待全部执行完成后,再返回校验结果。 - 第三步:修改
update方法适配异步逻辑
等待getInfoFromService的异步返回结果后,再执行resolve/reject逻辑。
完整可运行代码
class Foo { a: number = 0; constructor () { } public fakeService(data: number, callback: (sugestion:number, query:number) => void): void { // 模拟耗时的外部服务 var b = 42; var a = 12; setTimeout(() => { return callback(data * a + b, 0); }, 500) } // 新增:封装fakeService为返回Promise的方法 private fakeServicePromise(data: number): Promise<[sugestion: number, query: number]> { return new Promise((resolve) => { this.fakeService(data, (sugestion, query) => { resolve([sugestion, query]); }) }) } public async update() { // 调用多个服务获取数据 return new Promise(async (resolve, reject) => { // 等待异步方法返回结果 let valid: boolean = await this.getInfoFromService(); if (valid) { resolve("OK " + this.a); } else { reject("NOK " + this.a); } }) } private async getInfoFromService(): Promise<boolean> { // 收集所有并行调用的Promise const servicePromises: Promise<void>[] = []; for (let i=0; i<5; i++){ const p = this.fakeServicePromise(i).then(([sugestion]) => { this.a = Math.max(sugestion, this.a); }) servicePromises.push(p); } // 等待所有服务调用全部执行完成 await Promise.all(servicePromises); // 此时this.a已经更新为最终值,再做判断 return this.a == 90; } } const foo = new Foo(); // update方法需要返回Promise用于触发后续更新 foo.update() .then(res => { console.log(res); }) .catch(e => { console.log(e); });
运行结果说明
循环调用5次fakeService,i的取值是0~4,计算得到的sugestion最大值是4*12+42=90,所以最终会输出OK 90。
内容的提问来源于stack exchange,提问作者Nicolas M.
相关产品推荐
相关产品推荐

