我已经使用Koa建立了一个SSE连接,如下所示:
const Koa = require('koa');
const Router = require('koa-router');
const app = new Koa();
const router = new Router();
// Sets up the HTTP header and sends a message via SSE
function writeSSE(ctx, message) {
ctx.res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
'Access-Control-Allow-Origin': '*',
});
ctx.res.write(`id: 01\n`);
ctx.res.write(`data: ${message}\n\n`);
}
// Router Middleware
router.get('/stream', (ctx, next) => {
writeSSE(ctx, 'Stream reached.');
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(8080);当我的React组件开始连接时,如下所示:
new EventSource("http://localhost:8080/stream")然后,组件在后端接收由writeSSE方法发送的答案。
但出于某种原因,每隔3秒左右就会到达/stream 端点,就好像连接正在重新建立一样。
而前端的错误侦听器每次都捕获一个连接事件。
this.state.source.onerror = (e) => {
if (e.target.readyState == EventSource.CONNECTING) {
console.log("Connecting...");
}
};在后端,ctx.response等于{ status: 404, message: 'Not Found', header: {} }。
有谁知道这个问题的原因吗?这和我使用Koa的方式有关吗?
发布于 2019-03-20 15:26:40
这有点太晚了,但我将编写使用Koa的sse的经验。
ctx.respond = false用于绕过koa响应机制。const stream = require('stream');
const koa = require('koa');
const app = new koa();
app.use(async ctx => {
ctx.set({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
ctx.status = 200;
const stream = new stream.PassThrough()
ctx.body = stream; // here koa will pipe the ctx.res to stream and end the ctx.res when ever the stream ends.
let counter = 5;
const t = setInterval(() => {
stream.write(`data: hi from koa sse ${counter}`);
counter--;
if (counter === 0) {
stream.end();
clearInterval(t);
}
}, 1000);
});希望这对任何人都能在科亚上玩SSE游戏。
PS:如果代码有什么问题,请告诉我,我会改正的。
发布于 2018-12-29 01:40:20
我正在为SSE实现一个基于Koa的服务器。我遇到了同样的问题,下面是我的想法/工作解决方案:
据我所知,onmessage和onerror不断被调用的原因是客户端的EventSource对象正在发出错误事件。这会导致连接断开,从而导致客户端发送另一个请求,以将流初始化到服务器。从这里开始,这个过程将无限期地重复下去。
根据我自己的测试,由于从服务器发送回来的数据,EventSource发出了一个错误。根据文档,除了“文本/事件流”之外,作为内容类型的200个响应将导致失败。
在您的示例中,您已经将响应声明为“text/event-stream”,并将字符串传递到ctx.res.write方法中。虽然这看起来是正确的,而且实际上在使用类似的代码和Express时是有效的,但在Koa中它似乎不起作用。但是,如果您更改要写入流响应的“数据”(如本例这里 ),则会发现连接建立正确。
也许可以尝试以下几点:
//require Passthrough
const PassThrough = require('stream').PassThrough;
//then, in your writeSSE function, try this:
let stream = new PassThrough();
stream.write(`data: ${message}\n\n`);
ctx.res.write(stream);
我不能百分之百确定这一变化的原因。我最好的猜测是,Koa的ctx对象有一些东西可以防止普通字符串或模板文本被视为有效的文本/事件流数据,但这完全是假设(这就引出了为什么它在Express中工作的问题,但希望有一个更有知识的人能够为我们两个人回答这个问题)。从我在网上看到的其他片段来看,流方法是在Koa中采用的方法。
我不知道你的结果会是什么,因为看起来你可能使用了一个不同于我的版本的Koa,但我会尝试一下。我能够正确地建立起我的连接,做出这个小小的改变。
https://stackoverflow.com/questions/53295738
复制相似问题