SSE 在 Next.js 应用程序上下文中传输响应以及使用 Vercel Edge 函数的示例:
https://docs.ai-jsx.com/tutorials/aijsxTutorials/part5-nextjs#the-aijsx-edge-function
上面使用了函数toStreamResponse,它创建/返回一个新的响应对象。因此,此方法不与 Express 集成,Express 要求您使用路由处理程序中可用的现有响应对象。我如何将这两种方法结合在一起?我尝试过使用 toTextStream 函数:
routes.post("/chat-stream", async (req, res) => {
const { system = "", user = "" } = req.body || {};
if (!user) {
res.sendStatus(400);
return;
}
const RequestEl = getRequestEl(user, system);
const stream = toTextStream(RequestEl);
const reader = stream.getReader();
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Connection", "keep-alive");
res.setHeader("Cache-Control", "no-cache");
res.flushHeaders();
const pump = () => {
reader
.read()
.then(({ value, done }) => {
if (done) {
res.end();
return;
}
res.write(value);
pump();
})
.catch((err) => {
console.error(err);
if (!res.headersSent) {
res.status(500);
}
res.end();
});
};
pump();
});
使用上述内容,我可以在 Chrome 开发工具中看到响应流回,但客户端 AI.JSX 提供的 React 挂钩不会报告收到的任何数据。换句话说,这个:
const { error, current, fetchAI } = useAIStream({});
始终报告 error
和
current
均为空。
toStreamResponse
直接拉入我的 Express 应用程序并使用流管道(尽管我不确定为什么管道调用中需要 any ):
routes.post("/chat-stream", async (req, res) => {
const { system = "", user = "" } = req.body || {};
if (!user) {
res.sendStatus(400);
return;
}
const RequestEl = getRequestEl(user, system);
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Connection", "keep-alive");
res.setHeader("Cache-Control", "no-cache");
res.flushHeaders();
const renderResult = createRenderContext().render(RequestEl, {
stop: () => false,
map: (x) => x,
});
const eventStream = toEventStream(renderResult)
.pipeThrough(
new TransformStream({
transform(streamEvent, controller) {
controller.enqueue(`data: ${JSON.stringify(streamEvent)}\n\n`);
},
})
)
.pipeThrough(new TextEncoderStream());
pipeline(eventStream as any, res)
.then(() => {
res.end();
})
.catch((err) => {
console.error(err);
if (!res.headersSent) {
res.sendStatus(500);
}
res.end();
});
});