Javascript 是间隔阻塞吗?

Javascript 是间隔阻塞吗?,javascript,node.js,event-loop,Javascript,Node.js,Event Loop,我有以下节点应用程序 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":

我有以下节点应用程序

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

});
我正在使用它与我的客户端应用程序一起使用服务器端事件。当我浏览到它开始立即返回。如果我在另一个浏览器窗口中打开URI,那么它将需要几秒钟的时间才能做出响应,但是它工作正常

所以我的问题是setInterval阻塞,或者对于性能差有其他解释吗?基于这一点,它不应该是,但我不希望
constructse
需要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的一些限制,或者是我的一个错误。

我认为性能不佳的原因与Node或setInterval本身无关,而是与您读取事件数据的方式有关。我做了一些搜索,并实现了3或4个不同的例子,这些例子都是在web上发现的服务器在节点上发送事件,它们都面临着相同的问题

我认为node.js不适合这个任务,这不符合我的想法

我试过了

  • 使用process.nextTick
  • 增加间隔
  • 使用setTimeout而不是setInterval
  • 使用express.js或node.js
  • 使用一些节点模块,如和
  • 我正要开始使用或或其他服务器平台进行测试,试图找出问题所在,然后我想到编写一个小页面,使用EventSourceAPI获取事件。当我这样做的时候,一切都很好,而且在之前使用Chrome的测试中,我看到SSE请求在网络选项卡中包含一个额外的选项卡,称为EventStream,这是被尊重的,但是内容是空的,即使数据定期到达

    这让我相信,可能是浏览器没有以错误的方式正确解释请求,因为它是使用地址栏而不是EventSourceAPI请求的。原因我不知道,但我举了一个小例子,绝对没有糟糕的表现

    我这样修改了你的代码

  • 向网站的根目录添加另一个路由以进行测试

    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> 
    
    
    服务器发送事件演示
    document.addEventListener(“DOMContentLoaded”,函数(){
    var es=new EventSource('/api/time'),
    关闭=错误,
    ul=文件查询选择器(“ul”);
    es.onmessage=函数(ev){
    李华;
    如果(关闭)返回;
    li=document.createElement(“li”);
    li.innerHTML=“消息:”+ev.data;
    ul.儿童(li);
    };
    es.addEventListener('end',函数(){
    结束()
    关闭=真
    },对);
    es.onerror=函数(e){
    关闭=真
    };
    },假);
    
  • {Edit}


    我还想指出,感谢@Rodrigo Medeiros,使用
    curl
    请求
    /api/time
    ,没有表现出性能差,这强化了这是一个与浏览器相关的问题的想法。

    我浏览[URI]和“我在另一个浏览器窗口中打开URI”之间的区别是什么,
    setInterval
    确实没有阻塞。可能您遇到了
    res
    的一些缓冲行为,需要刷新输出?Bergi。我的意思是,当原始连接仍然打开时,我发出第二个请求。@RodrigoMedeiros这不是重复的。您引用的问题使对其他资源的请求过快,而这是关于服务未完成的请求。虽然问题的原因可能与此相关,但解决方案并非如此。您无法减少此问题中的请求数,因为根本没有请求。我增加了间隔,问题依然存在。您在浏览器开发工具的“网络”选项卡中看到了什么?有数据吗?非常感谢你的帮助。这是有道理的,打卷发没有任何问题。@baynezy不客气。我试图将chrome配置为使用http/1.0来检查这是否与RFC 2616第8节中所述的http/1.1持久连接有关,以提供更准确的答案,但我无法这样做。找不到相应的chrome设置:(