如何更新Apollo订阅中的变量?解决会话ID未更新问题
解决Apollo订阅变量无法动态更新的问题
核心问题分析
你当前的订阅是在服务初始化时一次性获取sessionSubject的值,后续会话ID更新时没有重新创建订阅,导致变量始终停留在初始的null状态。要实现变量动态更新,需要让订阅逻辑响应会话状态的变化。
解决方案:用RxJS switchMap 动态切换订阅
利用sessionSubject(应为BehaviorSubject或类似可观察对象)的特性,监听其值的变化,每当会话ID有效时,自动创建新的Apollo订阅并取消旧订阅。
修改客户端 session.service.ts 代码
import { filter, switchMap } from 'rxjs'; constructor(private apollo: Apollo, private sessionSubject: BehaviorSubject<Session | null>) { // 初始化动态订阅逻辑,而非直接执行单次订阅 this.setupDynamicSessionSubscription(); } private setupDynamicSessionSubscription() { this.sessionSubject.pipe( // 仅处理存在有效会话ID的状态 filter(session => !!session?.id), // 会话ID更新时,取消旧订阅并创建新订阅 switchMap(session => { return this.apollo.subscribe({ query: SESSIONS_SUBSCRIPTION, variables: { id: session.id } }); }) ).subscribe({ next: (data) => { // 处理收到的会话通知 console.log('会话通知:', data); }, error: (err) => { // 处理订阅错误 console.error('订阅失败:', err); } }); }
服务端 session.resolvers.js 配合逻辑
确保withFilter正确使用客户端订阅传递的id变量过滤通知,只推送给对应会话的用户:
const { withFilter } = require('apollo-server'); module.exports = { Subscription: { sessionNotification: { subscribe: withFilter( () => pubsub.asyncIterator('SESSION_NOTIFICATION'), (payload, variables) => { // 匹配通知的会话ID与订阅的会话ID return payload.sessionNotification.sessionId === variables.id; } ) } } };
关键说明
switchMap会在每次会话ID更新时自动取消之前的订阅,避免无效的连接占用资源。filter确保只有当会话ID存在时才创建订阅,减少不必要的服务端请求。- 当用户退出会话,
sessionSubject发出null时,filter会拦截,自动终止当前订阅。
内容的提问来源于stack exchange,提问作者Peter Boomsma
相关产品推荐
相关产品推荐

