如何将Nitro API流式数据传入Pinia Store并在Nuxt组件中使用?
问题原因
服务器端的Pinia Store实例和客户端的是完全独立的两个实例,你在Nitro服务器里更新的是服务器内存中的Store数据,客户端的Store根本接收不到这个更新,所以浏览器里看不到变化。
解决方案
1. 修改Nitro API,通过SSE推送流式数据
把原来直接操作Pinia的逻辑改成向客户端发送SSE事件:
export default defineEventHandler(async (event) => { const config = useRuntimeConfig() const body = await readBody(event) // 设置SSE响应头 event.res.setHeader('Content-Type', 'text/event-stream') event.res.setHeader('Cache-Control', 'no-cache') event.res.setHeader('Connection', 'keep-alive') const stream = await openai.beta.threads.createAndRunStream({ assistant_id: '你的ID', thread: { messages: [ { role: 'user', content: body.prompt || "Explain deep learning to a 5 year old." } ] } }) stream .on('textDelta', async (textDelta, snapshot) => { // 向客户端发送SSE事件 event.res.write(`data: ${JSON.stringify({ type: 'textDelta', data: snapshot })}\n\n`) }) .on('toolCallDelta', async (toolCallDelta, snapshot) => { if (toolCallDelta.type === 'code_interpreter') { let output = '' if (toolCallDelta.code_interpreter.input) { output += toolCallDelta.code_interpreter.input } if (toolCallDelta.code_interpreter.outputs) { output += '\noutput >\n' toolCallDelta.code_interpreter.outputs.forEach((outputItem) => { if (outputItem.type === 'logs') { output += `\n${outputItem.logs}\n` } }) } // 发送工具调用的输出 event.res.write(`data: ${JSON.stringify({ type: 'toolCallDelta', data: output })}\n\n`) } }) .on('textDone', async () => { // 发送结束信号 event.res.write(`data: ${JSON.stringify({ type: 'done' })}\n\n`) event.res.end() }) .on('error', (err) => { console.error('Stream error:', err) event.res.write(`data: ${JSON.stringify({ type: 'error', data: err.message })}\n\n`) event.res.end() }) // 防止请求被提前关闭 event.on('close', () => { stream.abort() }) return new Promise(() => {}) // 保持连接打开 })
2. 客户端监听SSE并更新Pinia Store
在Pinia Store里添加SSE监听逻辑:
// 在Pinia Store里添加方法 export const useChatStore = defineStore('chat', () => { const streamOutput = ref({ value: "", annotations: [] }) const setStreamOutput = (output) => { console.log("setStreamOutput", output) streamOutput.value = output } // 新增:发起SSE请求并监听 const fetchStreamData = async (prompt) => { const eventSource = new EventSource(`/api/your-stream-endpoint?prompt=${encodeURIComponent(prompt)}`) eventSource.onmessage = (event) => { const data = JSON.parse(event.data) switch (data.type) { case 'textDelta': setStreamOutput(data.data) break case 'toolCallDelta': // 这里根据需求合并数据 setStreamOutput({ ...streamOutput.value, value: streamOutput.value.value + data.data }) break case 'done': eventSource.close() break case 'error': console.error('Stream error:', data.data) eventSource.close() break } } eventSource.onerror = (err) => { console.error('SSE error:', err) eventSource.close() } return eventSource } return { streamOutput, setStreamOutput, fetchStreamData } })
3. 在客户端组件中调用
<template> <div>{{ chatStore.streamOutput.value }}</div> <button @click="startStream">开始流式请求</button> </template> <script setup> const chatStore = useChatStore() const startStream = async () => { await chatStore.fetchStreamData("Explain deep learning to a 5 year old.") } </script>
关键说明
- Nitro服务器和客户端运行在不同环境,各自维护独立的Pinia实例,服务器端的Store更新无法直接同步到客户端。
- 使用SSE(Server-Sent Events)是处理流式响应并同步到客户端的标准方案,适合单向的服务器到客户端的数据流。
- 如果需要双向通信,可以考虑用WebSocket,但SSE对于这种AI流式输出场景已经足够。
内容的提问来源于stack exchange,提问作者av0000
相关产品推荐
相关产品推荐

