javascript - EventSource primește toate segmentele odată când face streaming prin Nextjs API Routes
Problemă
Încerc să transmit date către frontend-ul meu React prin EventSources, ceea ce funcționează într-un fel. Problema este că primesc toate bucățile de date dintr-o dată, în loc să le primesc treptat. Ceea ce înăbușe scopul metodei, deoarece acum este practic o cerere GET.
Cod
Folosesc rutele API Next.js și acesta este codul meu pe această rută:
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
answerStream.data
.on("data", (chunk: string) => res.write(chunk))
.on("error", (error: Error) => {
console.error(error);
res.end();
})
.on("end", () => res.end());
Acesta este codul în Frontend:
const eventSource = new EventSource(url);
eventSource.addEventListener("message", e => {
try {
if (e.data == "[DONE]") eventSource.close();
else {
const messageObject = JSON.parse(e.data);
setArticle(state => (state += messageObject?.choices[0]?.text));
}
} catch (error) {
console.log(error);
}
});
eventSource.addEventListener("close", e => {
console.log("Connection closed with the server");
setSubmitting(false);
});
eventSource.addEventListener("error", e => {
setError(e?.message || "Leider ist ein Fehler aufgetreten");
setSubmitting(false);
eventSource.close();
});
Informații
Există ceva greșit în implementarea mea? Sau Next.js are un mod ciudat de a trata EventSource?
Răspuns #1
Soluție
Ok, am găsit soluția în această discuție de pe Github:
Se pare că problema este că middleware-ul adaugă o codificare gzip pe care browserul a negociat-o folosind antetul
Pentru a rezolva acest lucru, este necesar să suprascrieți acel comportament prin adăugarea 'Content-Encoding': 'none' la anteturile de pe server:
res.writeHead(200, {
Connection: 'keep-alive',
'Content-Encoding': 'none',
'Cache-Control': 'no-cache',
'Content-Type': 'text/event-stream',
});
Alternativ, s-ar putea folosi un server.js personalizat.
Răspunsul #2
daaaaaaa, asta căutam, aveam ceva similar, am petrecut aproximativ 2 zile de frustrare încercând să înțeleg. iată ce am ajuns să fac/ce am avut, în plus era un antet de chunk cu care experimentam:
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
res.setHeader("Transfer-Encoding", "chunked");
res.setHeader("Content-Encoding", "none");
