Javascript 如何管理多个侦听器?
我对听众有意见。我在自己开发的节点中的http侦听器中有多个输入。我用过这样的东西:Javascript 如何管理多个侦听器?,javascript,node.js,node-red,Javascript,Node.js,Node Red,我对听众有意见。我在自己开发的节点中的http侦听器中有多个输入。我用过这样的东西: ... server.on(‘connection’, function(){ node.on(‘input’, function(){ // something to manage messages }); }); ... server.on('connection', function(){ function inputLis
...
server.on(‘connection’, function(){
node.on(‘input’, function(){
// something to manage messages
});
});
...
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);
});
我想选择何时停止侦听器(例如,当它找到特定的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);
node.removeListener()
如果您正确使用它,它将正常工作,因此我假设您没有正确使用它要正确地删除一个特定的侦听器,您必须向其传递您最初侦听的消息和相同的函数引用。这意味着您不能使用如下所示的匿名函数引用:
相反,您可以这样做:
...
server.on(‘connection’, function(){
node.on(‘input’, function(){
// something to manage messages
});
});
...
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);
});
在这里,代码创建一个本地函数(每次调用连接处理程序时该函数都是唯一的),然后将其与.on()
一起使用。这样,您就可以将完全相同的函数引用传递给.removeListener()
当您要删除该特定侦听器时。可能值得查看
node.once()
也有它自己的特定用途。它所做的是在下次事件触发后自动删除事件侦听器。如果这正是您想要的情况,它非常方便。但是,如果您想测试某个条件,并且仅在满足该条件并且有时需要看到多个事件时才删除事件处理程序对于事件,则不能使用.once()
另外,您的问题中包含非法的事件名称引号。这在Javascript中不起作用。您不应该在进行此类处理的字处理器中编辑代码。请始终使用文本编辑器
现在,您已经包含了更多的实际代码,似乎存在并发问题,因为您对所有请求使用相同的节点对象,因此无法区分哪个input
事件属于哪个请求。您需要解决该问题
有很多方法可以做到这一点,但这里有一种方法。您需要更改节点
对象,以便它接收您发送的唯一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);
@FabianoAmmirata-那么,这个答案能解决您的问题吗?如果不能,请解释原因。我编辑了我的答案,所以我会具体说明:我必须多次呼叫侦听器(因此node.one是不可能的)但每个http连接的旧侦听器都仍然存在。在我发布的代码中,它可以工作,但我想删除旧侦听器。当我使用RemovelListener时,它会删除找到的第一个进程,因此可能会删除另一个http连接的侦听器。这是一个并发问题。我刚刚编辑了我的帖子,你认为这是一个稳定的解决方案吗?@FabianoAmmirata-如果您只是想在侦听器第一次启动时删除它,那么只需使用.once()
。如果您对多个请求使用共享节点
对象,则会出现并发问题,因为您无法知道哪个事件属于哪个请求。请参阅我在回答中添加的内容。