Angular RxJS递归调用API直至状态为true的问题排查
RxJS循环检查文件状态问题修复
原代码的核心问题是循环检查文件状态的逻辑存在漏洞,导致只执行一次检查就进入后续流程。以下是修复后的代码及问题解析:
修复后的代码
this.homeService.auth().pipe( switchMap(authToken => { return this.homeService.uploadFile(this.masterFile); }), // 循环检查文件状态 switchMap(fileId => { let retries = 0; // 将重试计数器放在内部,避免全局污染 return this.homeService.fileStatus(fileId).pipe( expand(status => { // 状态为true或重试次数耗尽时,停止扩展 if (status === true || retries >= 50) { return EMPTY; } retries++; // 延迟2秒后再次调用状态检查接口 return timer(2000).pipe( switchMap(() => this.homeService.fileStatus(fileId)) ); }), // 持续接收值直到状态为true或重试耗尽,true参数确保最后一个值被发出 takeWhile(status => status === false && retries < 50, true), // 取最后一个值,确保只有最终状态被传递到下一个流程 last(), catchError(() => { throw new Error('Failed to confirm upload status after 50 retries'); }) ); }), switchMap((status: boolean) => { if (status === true) { return this.processFurther(); } // 状态为false时抛出错误,终止流程 throw new Error('File upload did not complete successfully'); }) ).subscribe(response => { console.log('All done'); // 原代码里的console.lot是笔误,修正为console.log }, error => { console.log('Error processing ', error); });
关键修复点
- 重试计数器作用域:将
retries声明在switchMap内部,避免全局变量导致的计数器异常,每次文件上传都会重置计数器。 - expand操作符逻辑修正:移除多余的
of(status),直接通过timer(2000)实现延迟后重新调用状态接口,确保每次重试都是真实的接口请求。 - 添加last()操作符:确保只传递最终的状态值(true或重试耗尽后的结果)到下一个
switchMap,避免中间状态干扰后续流程。 - 修正笔误:原代码中的
console.lot改为console.log。 - 状态异常处理:当最终状态为false时主动抛出错误,避免流程静默终止。
内容的提问来源于stack exchange,提问作者Ankit
相关产品推荐
相关产品推荐

