Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 正在终止节点中服务器发送的事件_Node.js_Google Chrome_Express_Firefox - Fatal编程技术网

Node.js 正在终止节点中服务器发送的事件

Node.js 正在终止节点中服务器发送的事件,node.js,google-chrome,express,firefox,Node.js,Google Chrome,Express,Firefox,我正在尝试将SSE与node+express结合使用:我使用快速路由拦截请求,然后通过直接写入头来启动SSE会话: res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache" }); 我继续使用“res.write()”s编写间歇有效负载 这在Chrome的EventSource上运行良好,直到我调用“.close()”结束会话为止。然后,连接保持挂起:Chrome不

我正在尝试将SSE与node+express结合使用:我使用快速路由拦截请求,然后通过直接写入头来启动SSE会话:

res.writeHead(200, {
    "content-type": "text/event-stream",
    "cache-control": "no-cache"
});
我继续使用“res.write()”s编写间歇有效负载

这在Chrome的EventSource上运行良好,直到我调用“.close()”结束会话为止。然后,连接保持挂起:Chrome不会重用连接来启动其他EventSource请求(或任何其他请求),并且node也不会在IncomingMessage实例上触发“关闭”事件

我的问题是:如何使用节点的http API正确处理“eventSource.close()


值得注意的是:

  • 由于我没有设置“内容长度”,节点自动采用“分块”传输编码(这在AFAIK中应该不是问题)。它还默认为“连接:保持活动”
  • 当我使用Firefox时,会话正常终止

当浏览器关闭事件源时,它会让服务器端知道。在服务器端,响应套接字对象(
res.socket
)将生成一个
end
事件,然后是一个
close
事件。您可以收听此事件并做出适当的响应

例如

如果您的服务器试图写入浏览器上关闭的套接字,则不应引发错误,但将从
res.write
返回
false

如果关闭事件源后服务器端代码和客户端代码都挂起,则两侧可能都有bug


更完整的原型,使用上面的
写头
代码

var app = new (require('express'));
var responses = [];

app.get("/", (req, res) => {
    res.status(200).send(`
<html>
    <script>
        var eventsource = null;

        function connect() {
            if (!eventsource) {
                eventsource = new EventSource("/sse");
                eventsource.onmessage = function(e) {
                    var logArea = window.document.getElementById('log');
                    logArea.value += e.data;
                };
            }
        }

        function disconnect() {
            if (eventsource) {
                var myeventsource = eventsource;
                eventsource = null;
                myeventsource.close();
            }
        }
    </script>
    <div>
        <span>
            <a href="javascript: connect()">Connect</a>
            <a href="javascript: disconnect()">Disconnect</a>
        <span>
    </div>
    <textarea id="log" style="width: 500px; height: 500px"></textarea>
</html>`);
});

app.get("/sse", (req, res) => {
    res.writeHead(200, {
        "content-type": "text/event-stream",
        "cache-control": "no-cache"
    });

    res.socket.on('end', e => {
        responses = responses.filter(x => x != res);
        res.end();
    });

    responses.push(res);
});

app.listen(8080);

setInterval(() => {
    responses.forEach(res => {
        res.write('data: .\n\n');
    });
}, 100);
var-app=new(require('express'));
var响应=[];
应用程序获取(“/”,(请求,请求)=>{
资源状态(200)。发送(`
var eventsource=null;
函数连接(){
如果(!eventsource){
eventsource=新的eventsource(“/sse”);
eventsource.onmessage=函数(e){
var logArea=window.document.getElementById('log');
logArea.value+=e.data;
};
}
}
功能断开(){
如果(事件源){
var myeventsource=eventsource;
eventsource=null;
myeventsource.close();
}
}
`);
});
应用程序获取(“/sse)”,(请求,请求)=>{
文书标题(200{
“内容类型”:“文本/事件流”,
“缓存控制”:“无缓存”
});
res.socket.on('end',e=>{
responses=responses.filter(x=>x!=res);
res.end();
});
响应。推送(res);
});
app.listen(8080);
设置间隔(()=>{
响应。forEach(res=>{
res.write('data:.\n\n');
});
}, 100);

当浏览器关闭事件源时,它会让服务器端知道。在服务器端,响应套接字对象(
res.socket
)将生成一个
end
事件,然后是一个
close
事件。您可以收听此事件并做出适当的响应

例如

如果您的服务器试图写入浏览器上关闭的套接字,则不应引发错误,但将从
res.write
返回
false

如果关闭事件源后服务器端代码和客户端代码都挂起,则两侧可能都有bug


更完整的原型,使用上面的
写头
代码

var app = new (require('express'));
var responses = [];

app.get("/", (req, res) => {
    res.status(200).send(`
<html>
    <script>
        var eventsource = null;

        function connect() {
            if (!eventsource) {
                eventsource = new EventSource("/sse");
                eventsource.onmessage = function(e) {
                    var logArea = window.document.getElementById('log');
                    logArea.value += e.data;
                };
            }
        }

        function disconnect() {
            if (eventsource) {
                var myeventsource = eventsource;
                eventsource = null;
                myeventsource.close();
            }
        }
    </script>
    <div>
        <span>
            <a href="javascript: connect()">Connect</a>
            <a href="javascript: disconnect()">Disconnect</a>
        <span>
    </div>
    <textarea id="log" style="width: 500px; height: 500px"></textarea>
</html>`);
});

app.get("/sse", (req, res) => {
    res.writeHead(200, {
        "content-type": "text/event-stream",
        "cache-control": "no-cache"
    });

    res.socket.on('end', e => {
        responses = responses.filter(x => x != res);
        res.end();
    });

    responses.push(res);
});

app.listen(8080);

setInterval(() => {
    responses.forEach(res => {
        res.write('data: .\n\n');
    });
}, 100);
var-app=new(require('express'));
var响应=[];
应用程序获取(“/”,(请求,请求)=>{
资源状态(200)。发送(`
var eventsource=null;
函数连接(){
如果(!eventsource){
eventsource=新的eventsource(“/sse”);
eventsource.onmessage=函数(e){
var logArea=window.document.getElementById('log');
logArea.value+=e.data;
};
}
}
功能断开(){
如果(事件源){
var myeventsource=eventsource;
eventsource=null;
myeventsource.close();
}
}
`);
});
应用程序获取(“/sse)”,(请求,请求)=>{
文书标题(200{
“内容类型”:“文本/事件流”,
“缓存控制”:“无缓存”
});
res.socket.on('end',e=>{
responses=responses.filter(x=>x!=res);
res.end();
});
响应。推送(res);
});
app.listen(8080);
设置间隔(()=>{
响应。forEach(res=>{
res.write('data:.\n\n');
});
}, 100);