React Native中Fetch获取OpenAI流式响应失败问题求助
React Native中Fetch API无法获取response.body实现流式处理OpenAI响应的解决方案
问题概述
通过Node+Express转发OpenAI的流式文本响应到React Native客户端时,React Native的Fetch API不支持ReadableStream,调用response.body返回undefined,无法通过getReader()逐块处理文本。非流式场景下用response.text()可正常获取内容,尝试过RN-fetch-blob、react-native-fetch-api等polyfill均无效。
服务器端已能正常输出分块内容:
Hi ! How can I assist you today ?
服务器端示例代码
app.post("/gptText", async (req, res) => { try { const requestBody = { model: "gpt-4", messages: [ { role: "user", content: "Say 'hi'", }, ], stream: true, }; const completion = await openai.chat.completions.create(requestBody); res.setHeader("Content-Type", "text/plain"); res.setHeader("Transfer-Encoding", "chunked"); for await (const chunk of completion) { const [choice] = chunk.choices; const { content } = choice.delta; if (content !== undefined) { console.log(content); res.write(content); } } res.end(); } catch (error) { console.error("Error: ", error); res.status(500).json({ error }); } });
客户端尝试代码(无效)
const response = await fetch('YOUR_SERVER_URL/gptText', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({/* 请求参数 */}) }).then((response) => { console.log(response.body); // 输出undefined });
可行解决方案
方案1:使用react-native-blob-util处理流式响应
react-native-blob-util是RN-fetch-blob的替代库,支持流式响应处理:
- 安装依赖
npm install react-native-blob-util # 或 yarn add react-native-blob-util
- 客户端代码实现
import ReactNativeBlobUtil from 'react-native-blob-util'; const fetchStream = async () => { const response = await ReactNativeBlobUtil.fetch('POST', 'YOUR_SERVER_URL/gptText', { 'Content-Type': 'application/json', }, JSON.stringify({/* 请求参数 */})); // 获取响应流 const stream = response.blobStream(); // 逐块读取数据 stream.onData((chunk) => { // 将二进制chunk转为文本 const text = String.fromCharCode(...new Uint8Array(chunk)); console.log('收到分块内容:', text); // 这里处理文本,比如更新UI }); stream.onEnd(() => { console.log('流式响应结束'); }); stream.onError((error) => { console.error('流式请求出错:', error); }); };
方案2:改用Server-Sent Events(SSE)
修改服务器端输出SSE格式的响应,React Native可通过第三方库接收:
- 修改服务器端代码
app.post("/gptText", async (req, res) => { try { const requestBody = { model: "gpt-4", messages: [ { role: "user", content: "Say 'hi'", }, ], stream: true, }; const completion = await openai.chat.completions.create(requestBody); // 设置SSE响应头 res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); for await (const chunk of completion) { const [choice] = chunk.choices; const { content } = choice.delta; if (content !== undefined) { // 按SSE格式发送数据 res.write(`data: ${content}\n\n`); // 强制刷新响应 await new Promise(resolve => res.flushHeaders(resolve)); } } // 发送结束信号 res.write('data: [DONE]\n\n'); res.end(); } catch (error) { console.error("Error: ", error); res.status(500).write(`data: {"error": "${error.message}"}\n\n`); res.end(); } });
- 客户端代码(使用react-native-sse库)
npm install react-native-sse # 或 yarn add react-native-sse
import { EventSource } from 'react-native-sse'; const connectSSE = () => { const es = new EventSource('YOUR_SERVER_URL/gptText', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({/* 请求参数 */}), }); es.addEventListener('message', (event) => { if (event.data === '[DONE]') { es.close(); console.log('SSE连接结束'); return; } console.log('收到SSE内容:', event.data); // 处理文本更新UI }); es.addEventListener('error', (error) => { console.error('SSE出错:', error); es.close(); }); };
方案3:WebSocket替代HTTP流式
通过WebSocket建立持久连接,实时传输分块数据:
- 服务器端添加WebSocket支持(使用ws库)
npm install ws
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws) => { ws.on('message', async (data) => { try { const requestBody = JSON.parse(data); const completion = await openai.chat.completions.create({ ...requestBody, stream: true, }); for await (const chunk of completion) { const [choice] = chunk.choices; const { content } = choice.delta; if (content !== undefined) { ws.send(content); } } ws.send('[DONE]'); } catch (error) { ws.send(JSON.stringify({ error: error.message })); } }); });
- 客户端代码
const ws = new WebSocket('ws://YOUR_SERVER_IP:8080'); ws.onopen = () => { // 发送请求参数 ws.send(JSON.stringify({ model: "gpt-4", messages: [ { role: "user", content: "Say 'hi'" } ] })); }; ws.onmessage = (event) => { if (event.data === '[DONE]') { ws.close(); console.log('WebSocket连接结束'); return; } console.log('收到WebSocket内容:', event.data); // 处理文本更新UI }; ws.onerror = (error) => { console.error('WebSocket出错:', error); };
内容的提问来源于stack exchange,提问作者Yafim Simanovsky
相关产品推荐
相关产品推荐

