Javascript Node.js:使用EventEmitter和Express 4.x进行长轮询|捕获请求关闭

Javascript Node.js:使用EventEmitter和Express 4.x进行长轮询|捕获请求关闭,javascript,jquery,node.js,ajax,express,Javascript,Jquery,Node.js,Ajax,Express,我正在使用JQuery的ajax请求(xhr)长时间轮询node.js路由。这将向我的Express服务器发送GET请求,并侦听消息总线事件。我正在设置GET请求的超时(因为我的代理将终止长请求)。因此,在超时之后,客户端应该向服务器发送一个中止事件 我想捕获中止/关闭/完成事件,并删除相关的消息总线侦听器/订阅者 但我很挣扎。我尝试了req.on(“close”)和完成的npm模块,但这对我不起作用。在阅读了node:的http文档之后,我也不是很聪明 有没有办法对付这只野兽?还是更好的方法来

我正在使用JQuery的ajax请求(xhr)长时间轮询node.js路由。这将向我的Express服务器发送GET请求,并侦听消息总线事件。我正在设置GET请求的超时(因为我的代理将终止长请求)。因此,在超时之后,客户端应该向服务器发送一个中止事件

我想捕获中止/关闭/完成事件,并删除相关的消息总线侦听器/订阅者

但我很挣扎。我尝试了req.on(“close”)和完成的npm模块,但这对我不起作用。在阅读了node:的http文档之后,我也不是很聪明

有没有办法对付这只野兽?还是更好的方法来删除侦听器以防止内存泄漏

服务器端基本要素:

// server.js
var express = require("express");
var EventEmitter = require("events").EventEmitter;
var messageBus = new EventEmitter();
messageBus.setMaxListeners(20);

var REST_PORT = (process.env.PORT || 5000);
var app = express();

app.get("/events", (req, res) => {
    var listener = function(res) {
        messageBus.once("message", function(data) {
            res.status(200).json(data);
        });
    };
    req.on("abort", function() { //I tried also "aborted", "close", "closed", "finish", "finished"..no luck
        messageBus.removeListener("message", listener);
    });

    listener(res);
    console.log("Total listeners to 'message' events:", messageBus.listeners("message").length);
});

// other messageBus.emit logic ..

app.listen(REST_PORT, () => {
    console.log("Application ready on port " + REST_PORT);
});
//client.js
$.ajax({
    method: "GET",
    async: true,
    url: "/events",
    success: function(data) {
        callback(data);
    },
    complete: function(request, status, err) {
        if (status == "timeout" || status == "success") {
            console.log("LOG: Normal long-polling timeout or successful poll, continuing.");
            longPoll();
        } else {
            console.warn("WARN: Server probably offline, retrying in 2 sec.");
            setTimeout(function() {
                longPoll();
            }, 2000);
        }
    },
    timeout: 30000
});
客户端要素:

// server.js
var express = require("express");
var EventEmitter = require("events").EventEmitter;
var messageBus = new EventEmitter();
messageBus.setMaxListeners(20);

var REST_PORT = (process.env.PORT || 5000);
var app = express();

app.get("/events", (req, res) => {
    var listener = function(res) {
        messageBus.once("message", function(data) {
            res.status(200).json(data);
        });
    };
    req.on("abort", function() { //I tried also "aborted", "close", "closed", "finish", "finished"..no luck
        messageBus.removeListener("message", listener);
    });

    listener(res);
    console.log("Total listeners to 'message' events:", messageBus.listeners("message").length);
});

// other messageBus.emit logic ..

app.listen(REST_PORT, () => {
    console.log("Application ready on port " + REST_PORT);
});
//client.js
$.ajax({
    method: "GET",
    async: true,
    url: "/events",
    success: function(data) {
        callback(data);
    },
    complete: function(request, status, err) {
        if (status == "timeout" || status == "success") {
            console.log("LOG: Normal long-polling timeout or successful poll, continuing.");
            longPoll();
        } else {
            console.warn("WARN: Server probably offline, retrying in 2 sec.");
            setTimeout(function() {
                longPoll();
            }, 2000);
        }
    },
    timeout: 30000
});

谢谢大家!

我建议完全中止您的自定义长轮询系统,并使用现有的消息传递/套接字类型系统之一。有许多是完全成形的。socket.io仍然是最受欢迎的,并且运行良好,但是像这样的一些替代方案可能更好

如果这对某人有所帮助,我最终决定以不同的方式实现长轮询,并在特定超时后在服务器端终止客户机请求。这对我来说非常有效,而且经过反思后,可能是比信任客户机正确关闭请求更好的机制

setTimeout(() => {
    if (!responded) {
        messageBus.removeListener("message", listener);
        res.status(204).end();
    }
}, 30000);

实际上,我从WebSocket(socket.io)开始,需要转向长轮询。我尝试的websocket包不支持我需要的一些基本安全功能。例如,我的问题。所以我个人的结论是WebSocket还不成熟(至少从安全角度来看),我应该回到“好的老”长期轮询。这个解决方案就是我在Python Web服务器中处理它的方式,我现在正在将它移植到Node。问题:在您的方案中,
get()
将其处理程序绑定到发射器的事件,然后。。。马上离开?而
res
对象一直持续到被处理?没关系,我假设是这样的,它起到了治疗作用。谢谢你的代码片段,帮助了我。很高兴它帮助了我:-)