[英]Browsers are not responding to Server-Sent Events until server closes connection
在我的Express / Node服务器上,我将内容类型设置为text/event-stream
:
res.writeHead(200, {
'Content-Type': 'text/event-stream'
});
然后,当一系列回调触发时,我将数据消息写入流并使用两个新行跟随它:
res.write('data: ' + JSON.stringify(data) + '\n\n');
如果我在服务器端添加日志记录,或者我只是使用curl
点击URL,我可以看到数据消息正在写入几秒钟。
但是,当我尝试在网页中使用这些数据消息时,没有任何反应。 (我在Mac上测试Chrome,Firefox和Safari。)以下是网页的样子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Testing</title>
</head>
<body>
<h1>Server-Sent Events Test</h1>
<script>
var source = new EventSource('/library/search?q=medicine&async');
source.onmessage = function(e) {
document.body.innerHTML += JSON.parse(e.data).name + '<br>';
};
</script>
</body>
</html>
如果我在服务器端添加一个关闭连接的最终回调(使用res.end()
),那么浏览器会立即响应所有数据消息,并且只发生一次res.end()
。 这似乎打败了使用Server-Sent Events的目的。
我需要改变什么(没有放弃并切换到XHR轮询)让浏览器在服务器发送事件到达时响应它们(这似乎是服务器发送事件的目的和用例)?
(显示问题的测试页面已经可用但是现在已经解决了这个问题,我已将其删除了。)
看起来你有一些正在进行压缩的中间件; 并且在执行此操作时,它将缓冲,直到您完成响应。 你可以用curl看到这个:
首先,裸GET:
curl <url>
接下来,添加一个Accept-Encoding
标头(类似于您的浏览器使用的标头):
curl <url> -H 'Accept-Encoding: gzip,deflate,sdch' --compressed
请注意--compressed
只是告诉curl
为你解压缩它。
您会注意到您在第一个上看到了预期的行为,但没有看到第二个上的预期行为。 这清楚地表明它与压缩有关。 我建议关闭该路由的压缩,或者找一个知道如何压缩每个帧的更智能的中间件。
它在Chrome中适用于我。 这是我的测试代码:
sse.js:
var app = require('express')();
app.get('/', function(req, res) {
res.sendFile(__dirname + '/sse.htm');
});
app.get('/events', function(req, res) {
var counter = 0;
res.writeHead(200, { 'Content-Type': 'text/event-stream' });
setInterval(function() {
res.write('data: ' + JSON.stringify({name: 'foo' + (counter++) }) + '\n\n');
}, 1000);
res.write('data: ' + JSON.stringify({name: 'foo' + (counter++) }) + '\n\n');
});
app.listen(8000);
sse.htm:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>Server-Sent Events Test</h1>
<script>
var source = new EventSource('/events');
source.onmessage = function(e) {
document.body.innerHTML += JSON.parse(e.data).name + '<br />';
};
source.onerror = function(e) {
source.close();
};
</script>
</body>
</html>
这会产生以下输出:
foo0 // one second later foo1 // two seconds later foo2 // three seconds later foo3 // etc.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.