SetInterval lock?

I have the following Node application

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() {

});

      

I am using it to consume server side events with my client application. When I go to http: // localhost: 8081 / api / time it immediately starts returning. If I open the URI in another browser window, it takes a few seconds before it responds, but then it works fine.

So my question is set to blocking Interval, or is there another explanation for the poor performance? Based on this answer, it shouldn't be, but I wouldn't expect it to constructSSE

take 5 seconds. However, I see a problem.

Thank.

Update As suggested what it might be related to express

, I removed it and just used the module 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");
};

      

It has the same behavior. So it looks like a Node limitation or bug.

+3


source to share


1 answer


I think the reason for the poor performance is not to do with the node or the setInterval itself, but with the way you read your event data. I do a little search and implement 3 or 4 different examples found on the internet of server-sent events on node and they all suffer from the same problem.

The thought of node.js not helping was a problem for me.

I tried

  • Using process.nextTick
  • Increasing the interval
  • Using setTimeout instead of setInterval
  • With express.js or just node.js
  • With some node modules like connect-sse and sse-stream

I was about to start testing with webworker-threads or a cluster module or other server framework trying to pinpoint the problem, and then I got the idea to write a small page to capture events using the EventSource API. When I did this, everything worked fine, moreover, in previous tests using Chrome I can see that in the Network tab the SSE request contains an additional tab named EventStream that was checked but the content was empty even when data arrived regularly ...



This led me to believe that perhaps the browser misinterpreted the request the wrong way because it was being requested using the address bar and not the EventSource API. I don't know the reasons for this, but I made a small example and there is absolutely no bad work.

I have changed your code as follows.

  • Added another route to the website root for testing

    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 file created

    <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}

I also want to point out, thanks to @Rodrigo Medeiros, that the request /api/time

with curl

does not show poor performance, which reinforces the idea that it is a browser-related issue.

+2


source







All Articles