如何在Node.js中使用Axios接收SSE实现GQL订阅?
在Node.js中用Axios通过text/event-stream实现GraphQL订阅的方案及问题排查
可行性说明
完全可以通过Axios结合text/event-stream(SSE)来订阅GraphQL服务,但需要注意Axios的流式响应配置,以及GraphQL订阅的请求格式要求。
你的代码问题分析
你代码里console.log("b")不执行的核心原因是:responseType配置位置错误:responseType是Axios请求配置的顶级属性,不是headers对象里的字段。你把它放在headers中,导致Axios没有以流式模式处理响应,而是默认等待整个响应完成才会resolveawait的Promise。而SSE是持续的流式响应,这个Promise永远不会resolve,console.log("b")也就不会执行。
另外需要注意:如果你的GraphQL订阅需要传递查询参数,当前的GET请求可能没有携带正确的订阅Query,服务端可能不会返回SSE流,但这不是导致"b"不打印的直接原因。
正确实现代码示例
下面是修正后的完整代码,包含流式响应处理和GraphQL订阅的请求格式:
const axios = require('axios'); async function gqlSseSubscription() { console.log("a"); try { // 替换成你的订阅Query,这里以GET请求为例,将Query编码后作为URL参数 const subscriptionQuery = encodeURIComponent(` subscription { // 示例订阅字段,替换成实际的订阅内容,比如newOrder { id amount } } `); const url = `http://localhost:4003/graphql?query=${subscriptionQuery}`; const response = await axios.get(url, { responseType: 'stream', // 正确的配置位置:顶级请求配置 headers: { 'Accept': 'text/event-stream', 'Cache-Control': 'no-cache', // 避免缓存SSE流 'Connection': 'keep-alive' } }); console.log("b"); // 监听流式数据 response.data.on('data', (chunk) => { const rawContent = chunk.toString('utf8'); // 解析SSE格式:按"data: 内容\n\n"的结构拆分事件 const events = rawContent.split('\n\n').filter(item => item.trim()); events.forEach(event => { if (event.startsWith('data:')) { const payload = event.slice(5).trim(); try { const gqlResponse = JSON.parse(payload); console.log('收到订阅更新:', gqlResponse); } catch (parseErr) { console.error('解析响应失败:', parseErr); } } }); }); // 监听流错误 response.data.on('error', (err) => { console.error('订阅流异常:', err); }); // 监听流结束 response.data.on('end', () => { console.log('订阅流已关闭'); }); } catch (requestErr) { console.error('订阅请求失败:', requestErr); } } // 执行订阅 gqlSseSubscription();
额外说明
虽然SSE可以实现GraphQL订阅,但GraphQL生态中更推荐使用WebSocket协议的专门客户端(如graphql-ws),因为WebSocket是双向通信,更适合订阅场景的实时交互,而SSE是单向的(服务器推给客户端),且部分场景下存在连接数限制。如果你的GraphQL服务支持WebSocket订阅,优先考虑这种方案。
内容的提问来源于stack exchange,提问作者lacaci3709
相关产品推荐
相关产品推荐

