RxJS如何防止路由跳转时前序请求未完成导致的重复HTTP请求
路由切换会话校验避免重复HTTP请求的解决方案
问题核心原因
当前实现中每次触发NavigationStart路由事件都会直接调用checkSession()发起请求,没有对前序未完成的请求做拦截,快速切换路由时就会产生重复的HTTP请求。
解决方案1:手动维护请求状态锁
新增布尔类型的状态位标记请求状态,请求发起前做判断,请求完成后重置标记:
// 组件内新增请求状态标记 private isCheckingSession = false; // 路由事件订阅逻辑 this.router.events.subscribe((ev) => { if (ev instanceof NavigationStart && !this.isCheckingSession) { this.checkSession(); } }); // 改造checkSession方法 checkSession() { this.isCheckingSession = true; // 替换为你实际的会话校验请求逻辑 this.http.post('/api/auth/check-session', {}) .subscribe({ next: (result) => { // 原有会话校验通过后的处理逻辑 }, error: (err) => { // 原有会话失效的处理逻辑,如跳转登录页 }, complete: () => { // 无论请求成功或失败,都重置状态标记 this.isCheckingSession = false; } }) }
解决方案2:RxJS exhaustMap操作符(更推荐)
利用RxJS内置的exhaustMap操作符特性:前序内部Observable未完成时,会直接忽略新的源事件,不需要手动维护状态标记:
import { filter, exhaustMap } from 'rxjs/operators'; // 改造后的路由订阅逻辑 this.router.events.pipe( // 过滤出NavigationStart事件 filter(ev => ev instanceof NavigationStart), // 前序校验请求未完成时,新的事件会被直接忽略 exhaustMap(() => this.checkSession()) ).subscribe({ next: (result) => { // 会话校验通过处理 }, error: (err) => { // 会话失效处理 } }); // checkSession调整为返回请求Observable,不要内部subscribe checkSession() { return this.http.post('/api/auth/check-session', {}); }
优化建议
如果你使用的是Angular框架,更建议将会话校验逻辑封装为
CanActivate路由守卫,不需要手动订阅路由事件,框架会自动在路由激活前执行校验,也可以避免重复请求问题。
内容的提问来源于stack exchange,提问作者zackstam
相关产品推荐
相关产品推荐

