如何在Fastify中实现REST接口的渐进式响应返回?
实现Fastify渐进式返回响应的两种方案
针对你这种先快速返回统计数据、再延迟返回详细结果的场景,有两种实用的实现方式:
一、使用Server-Sent Events(SSE)
SSE是专门为服务器向客户端推送实时数据设计的机制,天然适配这种分阶段返回的需求,客户端可以通过监听不同事件接收各阶段的数据。
fastify.get('/:query', async function (request, reply) { // 设置响应头,声明SSE格式 reply.header('Content-Type', 'text/event-stream') reply.header('Cache-Control', 'no-cache') reply.header('Connection', 'keep-alive') const { query } = request.params // 1. 快速获取并返回记录数 const count = await getCount(query) reply.write(`event: count\ndata: ${JSON.stringify({ count })}\n\n`) if (count > 0) { // 2. 执行耗时操作获取详细结果 const res = await getResults(query) // 返回详细数据,同时标记结束事件 reply.write(`event: results\ndata: ${JSON.stringify(res)}\n\n`) reply.write(`event: close\ndata: done\n\n`) } })
客户端接收示例:
const eventSource = new EventSource('/your-query-content') eventSource.addEventListener('count', (event) => { const data = JSON.parse(event.data) console.log('匹配记录数:', data.count) }) eventSource.addEventListener('results', (event) => { const data = JSON.parse(event.data) console.log('详细结果:', data) }) eventSource.addEventListener('close', () => { eventSource.close() })
二、使用分块传输编码的流式响应
如果不想依赖SSE,也可以利用HTTP分块传输编码,通过可读流分批次返回JSON数据,不过需要客户端处理完整的JSON拼接逻辑。
const { Readable } = require('stream') fastify.get('/:query', async function (request, reply) { const { query } = request.params // 创建可读流 const stream = new Readable({ read() {} }) // 设置响应头,开启分块传输 reply.header('Transfer-Encoding', 'chunked') reply.header('Content-Type', 'application/json') try { // 1. 先推送记录数(用逗号分隔,保证最终JSON格式合法) const count = await getCount(query) stream.push(JSON.stringify({ count }) + ',') if (count > 0) { // 2. 推送详细结果,补全JSON结构 const res = await getResults(query) stream.push(JSON.stringify({ results: res }) + '}') } else { // 无结果时补全JSON结尾 stream.push('}') } } catch (err) { stream.emit('error', err) } finally { // 结束流 stream.push(null) } return reply.send(stream) })
这种方式返回的是一个完整的JSON对象,浏览器会逐步接收分块数据,前端可通过监听progress事件感知数据到达,但需等待所有块接收完成才能解析成合法JSON。
内容的提问来源于stack exchange,提问作者punkish
相关产品推荐
相关产品推荐

