如何管理多个听众?

时间:2018-04-06 18:26:54

标签: javascript node.js node-red

我的听众有问题。我在自己开发的节点中的http侦听器中有多个输入。我用过这样的东西:

...    
server.on(‘connection’, function(){
        node.on(‘input’, function(){
            // something to manage messages
        });
    });
...

我想选择何时停止监听器(例如,当它找到特定的msg.payload时)。我尝试了“node.once(..”,“node.removeListener(..”但没有。你能帮助我吗?谢谢。

修改

所有代码:

var server = http.createServer((request, response) => {
    if (request.url == '/log' || request.url == '/log2'){
        let body = [];
        request.on('error', (err) => {
            console.error(err);
        }).on('data', (chunk) => {
            body.push(chunk);
        }).on('end', () => {
            body = Buffer.concat(body).toString();

            response.on('error', (err) => {
                console.error(err);
            });

            response.statusCode = 200;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Content-Type", "text/html");

            msg = {_msgid:"1c6db704.811319", topic:request.url ,payload: true};
            node.send(msg);


            function inputListener(msg) {
                console.log(msg.topic + " " + request.url);
                if (msg.topic == request.url)
                    response.end(JSON.stringify(msg.payload));

                //node.removeListener('input', inputListener);
            }
            node.on('input', inputListener);

        });
    } else {
        response.statusCode = 404;
        response.end();
    }
}).listen(8088);

编辑2

似乎可以使用这个技巧:

            function inputListener(msg) {
                if (msg.topic == request.url)
                    response.end(JSON.stringify(msg.payload));
                else
                    node.once('input', inputListener);
            }
            node.once('input', inputListener);

1 个答案:

答案 0 :(得分:1)

node.removeListener()如果您正确使用它将会正常工作,所以我假设您没有正确使用它。要正确使用.removeListener()删除一个特定的侦听器,您必须将最初侦听的消息和相同的函数引用传递给它。这意味着你不能使用像你所示的匿名函数引用:

相反,你可以这样做:

server.on('connection', function(){
    function inputListener(data) {
        // something to manage messages
        if (someCondition) {
            // if some condition is met, then remove this specific listener
            node.removeListener('input', inputListener);
        }
    }
    node.on('input', inputListener);
});

这里代码创建了一个本地函数(每次调用connection处理程序时它都是唯一的),然后将其与.on()一起使用。然后,当您要删除该特定侦听器时,允许您将完全相同的函数引用传递给.removeListener()。值得回顾doc for .removeListener()

node.once()也有自己的特定目的。它的作用是在下次事件触发后自动删除事件监听器。如果这正是您想要的情况,那将非常方便。但是,如果您想测试某些条件并且仅在满足条件时删除事件处理程序,并且有时需要查看事件的多次出现,那么您就不能使用.once()

P.S。您的问题包含您的活动名称的非法类型的引号。这在Javascript中不起作用。您永远不应该在执行该类处理的文字处理器中编辑代码。始终使用文本编辑器。

既然您已经包含了更多真实代码,那么您似乎遇到了并发问题,因为您为所有请求使用了相同的node对象,因此您无法使用告诉哪个input事件属于哪个请求。您需要解决该问题。

有很多方法可以做到,但这是一种方法。您需要更改node对象,以便它接收您发送的唯一ID,并将其与响应一起返回,以便您可以确定哪个响应与哪个请求相关。

const unique = require('node-unique');

var server = http.createServer((request, response) => {
    if (request.url == '/log' || request.url == '/log2'){
        let body = [];
        request.on('error', (err) => {
            console.error(err);
        }).on('data', (chunk) => {
            body.push(chunk);
        }).on('end', () => {
            body = Buffer.concat(body).toString();

            response.on('error', (err) => {
                console.error(err);
            });

            response.statusCode = 200;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Content-Type", "text/html");

            // generate unique id for this request
            let uniqueID = unique();
            msg = {_msgid:"1c6db704.811319", topic:request.url ,payload: true, id: uniqueID};
            node.send(msg);

            function inputListener(msg) {
                // ignore if this is not our msg
                if (msg.id === uniqueID) {
                    console.log(msg.topic + " " + request.url);
                    if (msg.topic == request.url)
                        response.end(JSON.stringify(msg.payload));

                    node.removeListener('input', inputListener);
                }
            }
            node.on('input', inputListener);
        });
    } else {
        response.statusCode = 404;
        response.end();
    }
}).listen(8088);