RxJS:使用switchMap操作符时如何不借助timeout处理取消请求
问题根因
switchMap 切换新的内部流时,会主动取消上一个未完成的内部流的订阅,取消属于订阅生命周期事件,不是流的error通知,所以默认不会被catchError捕获。
解决方案(无需使用timeout操作符)
方案1:需触发catchError执行错误逻辑
核心思路是将「轮询切换导致请求取消」的事件转换成流的error通知,同时复用外层轮询的时间间隔,不需要额外硬编码超时阈值:
const { NEVER, timer } = rxjs; const { catchError, switchMap, takeUntil, skip, defaultIfEmpty, tap, share } = rxjs.operators; // 多播轮询流,方便内部流监听下一次轮询触发事件 const poll$ = timer(0, 3000).pipe(share()); poll$.pipe( switchMap(() => timer(randomIntFromInterval(1, 4) * 1000).pipe( // 模拟HTTP请求 // 监听下一次轮询触发信号 takeUntil(poll$.pipe(skip(1))), // 请求被取消时takeUntil会发送完成通知,此处将空完成转换为标记值 defaultIfEmpty('REQUEST_CANCELLED'), // 识别取消标记,主动抛出错误即可进入catchError tap(val => { if (val === 'REQUEST_CANCELLED') throw new Error('请求超时被轮询切换取消') }), catchError((err) => { // 现在请求原生错误、取消转的错误都会触发该处逻辑 console.log('Caught error: ', err.message); return NEVER; }) ) ), ).subscribe({ next: (value) => console.log('Next triggered') }); // 原有工具方法保持不变 function randomIntFromInterval(min, max) { const value = Math.floor(Math.random() * (max - min + 1) + min); console.log(`Simulated HTTP call ${value}s`); return value; }
该方案的优势是完全复用外层轮询的3秒间隔作为超时判定标准,后续调整轮询间隔时不需要修改内部超时逻辑,避免出现阈值不一致的bug。
方案2:仅需处理取消逻辑无需触发catchError
如果不需要强制进入catchError,只是要在请求被取消时执行清理类逻辑,直接用finalize操作符即可,实现更简洁:
const { NEVER, timer } = rxjs; const { catchError, switchMap, finalize, tap } = rxjs.operators; timer(0, 3000).pipe( switchMap(() => { let isRequestCompleted = false; return timer(randomIntFromInterval(1, 4) * 1000).pipe( // 模拟HTTP请求 tap(() => isRequestCompleted = true), catchError(() => { isRequestCompleted = true; console.log('Caught request error'); return NEVER; }), finalize(() => { // 标记为false说明是被轮询切换取消的,执行对应逻辑即可 if (!isRequestCompleted) { console.log('请求被轮询切换取消,执行对应处理逻辑'); } }) ) }), ).subscribe({ next: (value) => console.log('Next triggered') }); // 原有工具方法保持不变 function randomIntFromInterval(min, max) { const value = Math.floor(Math.random() * (max - min + 1) + min); console.log(`Simulated HTTP call ${value}s`); return value; }
内容的提问来源于stack exchange,提问作者Aniruth
相关产品推荐
相关产品推荐

