I am using Strapi to build a backend API that sends real-time responses from a robot chat via Server-Sent Events (SSE). Users send messages to the backend, which requests a large model and expects to stream the data back in chunks via SSE. However, I’m encountering an issue where the interface seems to wait until the large model has processed all responses before starting to send data to the frontend, instead of streaming it piece by piece.
Here is the code implementation:
module.exports = createCoreController('api::bot.bot', ({ strapi }) => ({
chat: async (ctx, next) => {
const { body } = ctx.request;
const { key, type, msg } = (typeof(body) === 'string' ? JSON.parse(body) : body);
ctx.request.socket.setTimeout(0);
ctx.request.socket.setNoDelay(true);
ctx.request.socket.setKeepAlive(true);
ctx.set({
"Content-Type": "text/event-stream; charset=utf-8",
"Cache-Control": "no-cache",
"Connection": "keep-alive"
});
const stream = new PassThrough({ encoding: 'utf8' });
await ctx.send(stream, 200);
await next();
// Data fetching and processing logic
// ...
ctx.flushHeaders();
ctx.req.on('close', () => {
stream.end();
});
for await (let chunk of chats.iterator()) {
// Logic to handle each chunk
// ...
}
},
}));
Issue:
When I place the data reading and sending logic inside an asynchronous function (as shown below), the data streams to the frontend in real-time, chunk by chunk, instead of being sent all at once after complete processing:
(async () => {
for await (let chunk of chats.iterator()) {
// Logic to handle each chunk
// ...
}
})();
I would like to understand why the original implementation results in delayed data transmission and whether placing the processing logic in an asynchronous function is a valid solution. Additionally, if there are better practices or solutions, please advise.
Environment Information:
Strapi Version: v4
Node.js Version: v14.17.0
Database: PostgreSQL
Thank you for your assistance!