setInterval 是否阻塞?
Is setInterval blocking?
我有以下节点应用程序
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 window 那么它需要几秒钟才能响应,但是它可以正常工作。
所以我的问题是 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 的一些限制,或者是我的错误。
我认为性能不佳的原因与节点或 setInterval 本身无关,而是与您读取事件数据的方式有关。我做了一些搜索,并在节点上的服务器发送事件的网络上实现了 3 或 4 个不同的示例,它们都遇到了同样的问题。
认为 node.js 对任务没有好处的想法不适合我。
我试过了
- 使用process.nextTick
- 增加间隔
- 使用 setTimeout 代替 setInterval
- 与express.js或只是node.js
- 使用一些节点模块,例如 connect-sse and sse-stream
我正要开始使用 webworker-threads or the 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,使用 curl
向 /api/time
发出请求并没有显示出性能不佳,这强化了浏览器相关问题的想法。
我有以下节点应用程序
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 window 那么它需要几秒钟才能响应,但是它可以正常工作。
所以我的问题是 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 的一些限制,或者是我的错误。
我认为性能不佳的原因与节点或 setInterval 本身无关,而是与您读取事件数据的方式有关。我做了一些搜索,并在节点上的服务器发送事件的网络上实现了 3 或 4 个不同的示例,它们都遇到了同样的问题。
认为 node.js 对任务没有好处的想法不适合我。
我试过了
- 使用process.nextTick
- 增加间隔
- 使用 setTimeout 代替 setInterval
- 与express.js或只是node.js
- 使用一些节点模块,例如 connect-sse and sse-stream
我正要开始使用 webworker-threads or the 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,使用 curl
向 /api/time
发出请求并没有显示出性能不佳,这强化了浏览器相关问题的想法。