我有以下节点应用程序
var express = require("express"),
app = express();
app.get("/api/time", function(req, res) {
sendSSE(req, res);
});
function sendSSE(req, res) {
res.set({
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Access-Control-Allow-Origin": "*"
});
var id = (new Date()).toLocaleTimeString();
setInterval(function() {
constructSSE(res, id, (new Date()).toLocaleTimeString());
}, 5000);
constructSSE(res, id, (new Date()).toLocaleTimeString());
};
function constructSSE(res, id, data) {
res.write("id: " + id + "\n");
res.write("data: " + data + "\n\n");
}
var server = app.listen(8081, function() {
});
我正在使用它与我的客户端应用程序一起使用服务器端事件。当我浏览http://localhost:8081/api/time时,它会立即开始返回。如果我在另一个浏览器窗口中打开URI,那么它在响应之前需要几秒钟,但是它可以正常工作。
所以我的问题是setInterval阻塞,还是对性能不佳有其他解释?基于this answer它不应该是,但我不希望constructSSE
需要5秒。但是,我发现了一个问题。
感谢。
更新
根据建议,它可能与express
有关,我删除了它并使用了http
模块。
var http = require("http");
http.createServer(function(req, res){
if (req.url == "/api/time") {
sendSSE(req, res);
}
}).listen(8081);
function sendSSE(req, res) {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Access-Control-Allow-Origin": "*"
});
var id = (new Date()).toLocaleTimeString();
setInterval(function() {
constructSSE(res, id, (new Date()).toLocaleTimeString());
}, 5000);
constructSSE(res, id, (new Date()).toLocaleTimeString());
};
function constructSSE(res, id, data) {
res.write("id: " + id + "\n");
res.write("data: " + data + "\n\n");
};
它具有完全相同的行为。所以它看起来像Node的一些限制,或者是我的错误。
答案 0 :(得分:2)
我认为性能不佳的原因与节点或setInterval本身无关,而是与您读取事件数据的方式有关。我做了一些搜索,并在节点上的Server Sent Events网站上找到了3到4个不同的例子,他们都遇到了同样的问题。
认为node.js不适合这项任务并不适合我的想法。
我试过
我即将开始使用webworker-threads或cluster module或其他服务器平台进行测试,试图解决问题,然后我有了写一个小页面以使用EventSource获取事件的想法API。当我这样做时一切都运行得很好,而且在以前使用Chrome的测试中我看到在网络选项卡中SSE请求包含一个名为EventStream的附加选项卡,但是内容为空即使数据也是如此经常到达。
这让我相信,由于使用地址栏而不是EventSource API请求,浏览器可能无法以错误的方式正确解释请求。原因我不知道,但我做了一个例子,绝对没有糟糕的表现。
我改变了你的代码。
添加了另一条路径到网站根目录进行测试
var express = require("express"),
app = express();
// Send an html file for testing
app.get("/", function (req, res, next) {
res.setHeader('content-type', 'text/html')
fs.readFile('./index.html', function(err, data) {
res.send(data);
});
});
app.get("/api/time", function(req, res) {
sendSSE(req, res);
});
创建了index.html文件
<head>
<title>Server-Sent Events Demo</title>
<meta charset="UTF-8" />
<script>
document.addEventListener("DOMContentLoaded", function () {
var es = new EventSource('/api/time'),
closed = false,
ul = document.querySelector('ul');
es.onmessage = function (ev) {
var li;
if (closed) return;
li = document.createElement("li");
li.innerHTML = "message: " + ev.data;
ul.appendChild(li);
};
es.addEventListener('end', function () {
es.close()
closed = true
}, true);
es.onerror = function (e) {
closed = true
};
}, false);
</script>
</head>
<body>
<ul>
</ul>
</body>
<强> {编辑} 强>
我还要指出,感谢@Rodrigo Medeiros,向/api/time
curl
提出请求表明没有糟糕的表现,这加强了与浏览器相关的问题。