如何正确实现带轮询等待的多步API调用流程?
如何正确实现带轮询等待的多步API调用流程?
看起来你已经搭好了基本框架,但在轮询逻辑的控制、错误处理以及第三步调用的衔接上还有些问题,我来帮你把这个流程理顺并修正!
首先咱们再明确一遍需求:
- 第一步:调用API获取ID
- 第二步:用这个ID轮询第二个API,直到返回状态为
'C'(完成)才进入第三步;如果返回'E'(错误)或者超过21秒还没完成,就终止流程并抛出错误 - 第三步:用同一个ID调用第三个API获取最终详情
原代码的几个问题点
switchMap里没有返回this.secondCall(res),导致流没有正确衔接takeUntil的条件写反了,应该是当状态不是'P'时停止轮询,而不是反过来- 缺少对
'E'状态的错误处理,也没有衔接第三步调用
修正后的完整代码
import { interval, of, throwError } from 'rxjs'; import { switchMap, takeWhile, timeout, catchError, tap, filter } from 'rxjs/operators'; // 假设你的三个API方法定义如下 // firstCall(formData: any): Observable<string>; // secondCall(id: string): Observable<{ code: 'P' | 'C' | 'E' }>; // thirdCall(id: string): Observable<any>; this.firstCall(formData) .pipe( // 第一步成功拿到ID后,进入轮询流程 switchMap((id) => { return interval(3000).pipe( // 每3秒调用一次secondCall,用switchMap确保只保留最新请求 switchMap(() => this.secondCall(id)), // 捕获secondCall的网络错误,这里可以根据需求调整处理逻辑 catchError((error) => { console.warn('轮询请求出错:', error); // 返回'P'状态继续轮询,也可以用throwError直接终止流程 return of({ code: 'P' }); }), // 检查状态:如果是'E',主动抛出错误终止流程 tap((response) => { if (response.code === 'E') { throw new Error('处理过程出现错误'); } }), // 只要状态是'P'就继续轮询,一旦不是('C'或'E')就停止轮询 takeWhile((response) => response.code === 'P', true), // 第二个参数true保留最后一次非'P'的结果 // 超时控制:21秒内没拿到非'P'状态就触发超时错误 timeout(21000) ); }), // 只有当状态是'C'时,才调用第三个API获取详情 filter((response) => response.code === 'C'), switchMap((_) => this.thirdCall(id)), // 传入第一步拿到的ID调用第三个API // 全局捕获所有错误 catchError((error) => { console.error('流程出错:', error); throw error; // 可根据需求改成返回默认值或其他处理 }) ) .subscribe({ next: (finalData) => { console.log('最终详情:', finalData); }, error: (error) => { console.log('PROCESSING ERROR', error.message); } });
代码关键部分解释
- 轮询控制:用
takeWhile(response => response.code === 'P', true)来控制轮询节奏,第二个参数true会让流保留最后一次非'P'的结果,方便后续判断是成功完成还是出现错误 - 错误处理:
- 用
tap检测到'E'状态时主动抛出错误,直接终止流程 catchError处理secondCall的网络错误,这里选择返回'P'继续轮询,你也可以根据业务需求改成直接终止timeout(21000)确保超过21秒未完成就触发超时错误
- 用
- 第三步衔接:通过
filter只保留'C'状态的结果,再用switchMap调用第三个API,确保只有成功完成后才获取最终详情
这样整个流程就清晰闭环了,从第一步获取ID,到轮询等待完成,再到最后获取详情,所有分支情况都覆盖到了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

