后端批量Fetch场景下,React前端如何实时获取就绪结果?
实时返回单个请求结果的解决方案
当前后端通过Promise.all等待所有请求完成后一次性返回结果,导致前端必须等待全部请求结束才能拿到数据。要实现前端实时获取每个请求的结果,可采用以下两种方案:
方案一:使用Server-Sent Events(SSE)
这是最适配当前单向推送场景的轻量方案,后端在每个请求完成后立即向前端推送结果,前端实时接收并更新界面。
后端修改(以Node.js/Express为例)
将原有的一次性返回逻辑改为SSE流式响应:
app.get('/fetch-data', async (req, res) => { // 设置SSE响应头,确保浏览器识别为流 res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); const originList = // 你的源数据列表 const destinationList = // 你的目标数据列表 // 遍历所有请求,完成一个推一个 for (const origin of originList) { for (const destiny of destinationList) { const url = // 拼接目标请求URL try { const resp = await fetch(url); const data = await resp.json(); // 按SSE格式发送结果,必须以`data: 内容\n\n`结尾 res.write(`data: ${JSON.stringify({ text: data.text })}\n\n`); // 强制刷新缓冲区,确保消息立即发送到前端 await new Promise(resolve => res.flushHeaders(resolve)); } catch (err) { // 发送错误信息,方便前端排查 res.write(`data: ${JSON.stringify({ error: err.message })}\n\n`); await new Promise(resolve => res.flushHeaders(resolve)); } } } // 所有请求完成后发送结束信号 res.write('event: close\ndata: done\n\n'); res.end(); });
React前端实现
通过EventSource监听SSE流,实时更新状态:
import { useState, useEffect } from 'react'; function FetchResults() { const [results, setResults] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const eventSource = new EventSource('/fetch-data'); // 接收单个请求结果 eventSource.onmessage = (event) => { const data = JSON.parse(event.data); if (data.error) { console.error('请求出错:', data.error); return; } setResults(prev => [...prev, data.text]); }; // 监听结束事件,关闭连接 eventSource.addEventListener('close', () => { setIsLoading(false); eventSource.close(); }); // 组件卸载时清理连接,避免内存泄漏 return () => { eventSource.close(); }; }, []); return ( <div> <h2>实时获取请求结果</h2> {isLoading && <p>正在加载...</p>} <ul> {results.map((text, index) => ( <li key={index}>{text}</li> ))} </ul> </div> ); } export default FetchResults;
方案二:使用WebSocket(双向通信)
如果后续需要前端给后端发送交互指令(比如中途取消请求),可以用WebSocket实现双向实时通信。
后端示例(Node.js + ws库)
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', async (ws) => { const originList = // 你的源数据列表 const destinationList = // 你的目标数据列表 for (const origin of originList) { for (const destiny of destinationList) { const url = // 拼接目标请求URL try { const resp = await fetch(url); const data = await resp.json(); ws.send(JSON.stringify({ type: 'result', text: data.text })); } catch (err) { ws.send(JSON.stringify({ type: 'error', message: err.message })); } } } // 发送完成信号并关闭连接 ws.send(JSON.stringify({ type: 'done' })); ws.close(); });
React前端示例
import { useState, useEffect } from 'react'; function FetchResults() { const [results, setResults] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const ws = new WebSocket('ws://localhost:8080'); ws.onmessage = (event) => { const data = JSON.parse(event.data); switch (data.type) { case 'result': setResults(prev => [...prev, data.text]); break; case 'error': console.error('请求出错:', data.message); break; case 'done': setIsLoading(false); ws.close(); break; } }; // 组件卸载时关闭连接 return () => { ws.close(); }; }, []); return ( <div> <h2>实时获取请求结果</h2> {isLoading && <p>正在加载...</p>} <ul> {results.map((text, index) => ( <li key={index}>{text}</li> ))} </ul> </div> ); } export default FetchResults;
注意事项
- SSE仅支持后端向前端单向推送,实现简单,适合当前场景;WebSocket支持双向通信,适合复杂交互需求。
- 后端需处理单个请求的错误,避免某一个请求失败导致整个流程中断。
- 前端必须在组件卸载时关闭SSE/WebSocket连接,防止内存泄漏。
内容的提问来源于stack exchange,提问作者albertoivo
相关产品推荐
相关产品推荐

