Блокирует ли setInterval?
У меня есть следующее приложение узла
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 + "nn");
}
var server = app.listen(8081, function() {
});
Я использую его для использования серверных событий с моим клиентским приложением. Когда я перехожу к http://localhost:8081/api/time он сразу же начинает возвращаться. Если я открою URI в другом окне браузера, то это займет несколько секунд, прежде чем он ответит, однако тогда он работает нормально.
Итак, мой вопрос-блокировка setInterval, или есть какое-то другое объяснение плохой производительности? Исходя из этого ответа он не является предполагалось, что будет, но я не ожидал, что 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 + "nn");
};
Он имеет точно такое же поведение. Так что это выглядит как какое-то ограничение узла, или ошибка со стороны меня.
1 ответ:
Я думаю, что причина плохой производительности связана не с самим узлом или setInterval, а с тем, как Вы читаете данные о событиях. Я делаю небольшой поиск и реализую 3 или 4 различных примера, найденных в интернете серверных событий, отправленных на узел, и все они страдают от одной и той же проблемы.
Думая, что узел.Джей-ЭС не годился для такой задачи, которая не укладывалась у меня в голове.
Я пытался
- использование процесса.nextTick
- увеличение интервала
- использование setTimeout вместо setInterval
- с экспрессом.js или просто узел.js
- с некоторыми узловыми модулями, такими как connect-sse и sse-stream
Я собирался начать тестирование с использованием webworker-потоков или кластера модуль или другой серверной платформы пытаются придавить проблему и тогда у меня возникла идея написать небольшую страницу, чтобы захватить события, используя перегруженную EventSource API-интерфейс. Когда я делал это, все работало просто отлично, тем более в предыдущем тесты с использованием Chrome я вижу, что на вкладке Network запрос SSE содержит дополнительную вкладку eventstream, как было замечено, но содержимое было пустым, даже когда данные поступали регулярно.
Это привело меня к мысли, что, возможно, это был браузер, который неправильно интерпретировал запрос, потому что он был запрошен с помощью адресной строки, а не API EventSource. Причин для этого я не знаю но я привел маленький пример и там абсолютно нет бедных спектакль.
Я изменил ваш код вот так.
Добавлен еще один маршрут в корень сайта для тестирования
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); });
Создал индекс.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>
{Edit}
Я также хочу отметить, благодаря @Rodrigo Medeiros, что выполнение запроса к
/api/time
сcurl
не показывает плохой производительности, которая усиливает идею, что это проблема, связанная с браузером.