如何检测Apollo GraphQL订阅成功启动?基于graphql-ws与Observable
解决GraphQL订阅启动状态检测问题
核心思路
graphql-ws的订阅成功确认(服务器返回订阅接受响应)不会通过next回调触发,而是在订阅建立完成时会触发内部的ready信号。我们可以扩展client.subscribe的回调逻辑,在订阅成功建立时手动resolve Promise,同时保留原Observable的事件监听能力。
修改后的代码实现
function subscribeAndWaitForReady(operation) { return new Promise((resolve, reject) => { const observable = new Observable((observer) => { const unsubscribe = client.subscribe(operation, { next: (data) => observer.next(data), error: (err) => { observer.error(err); reject(err); // 订阅启动失败时reject Promise }, complete: () => observer.complete(), // 关键:监听graphql-ws的ready事件,确认订阅已成功启动 ready: () => { resolve(observable); // 订阅就绪后resolve,返回Observable供后续事件监听 }, }); return unsubscribe; }); }); }
使用示例
// 显示订阅启动进度条 showLoadingProgress(); try { const subscriptionObservable = await subscribeAndWaitForReady({ query: YOUR_SUBSCRIPTION_QUERY, variables: {}, }); // 订阅启动成功,隐藏进度条 hideLoadingProgress(); // 开始监听后续推送的事件 const unsubscribe = subscriptionObservable.subscribe({ next: (data) => console.log('收到事件:', data), error: (err) => console.error('订阅运行时错误:', err), complete: () => console.log('订阅结束'), }); // 需取消订阅时调用 // unsubscribe(); } catch (err) { // 订阅启动失败,隐藏进度条并处理错误 hideLoadingProgress(); console.error('订阅启动失败:', err); }
说明
graphql-ws的subscribe回调原生支持ready事件,该事件会在服务器确认订阅成功建立时触发,恰好作为Promise的resolve时机。- Promise的resolve值设为创建好的Observable,确保订阅启动成功后,能继续通过Observable监听后续的事件推送。
- 订阅启动阶段的错误会通过
error回调触发并reject Promise,便于统一处理启动失败场景。
内容的提问来源于stack exchange,提问作者A.A
相关产品推荐
相关产品推荐

