如果侦听器尚未添加,并且侦听器处理程序是匿名函数,则在nodeJS中添加侦听器

有没有办法来检查一个侦听器是否已经存在的node.js中的对象? 我想要实现以下场景:

  • 获取数据库的对象
  • 做一些操作
  • 添加监听器,如错误,结果,stream失等,如果相同的监听器尚未添加[假设对于所有的操作监听器操作是相同的]

我想优化添加侦听器的方式,如果我们尝试添加一个现有的侦听器,新的侦听器将不会被添加。 节点文档说:“ 不检查是否已经添加了侦听器。多个调用传递相同的eventName和listener的组合将导致添加和调用多个侦听器。

有没有办法解决它?
[编辑] – 添加一些示例代码

connpool.getConnection(function(err, connection) { var querystr = "Some valid SQL query"; connection.execute(querystr, data, function(err, rows) { if (err) { console.error(err); } connection.on('error', function(err){onErr(err,connection);}); do some stuff cleanup(connection); }); }) var onErr = function(err, connection) { console.error({"Error message"}); connection.release(); cleanup(connection); }; var cleanup = function(conn) { conn.removeListener('error',onErr); }; 

连接将包含一个数据库连接,它来自一个外部包。在声明connection.on('错误',function(错误){onErr(错误,连接);}); 我正在使用一个匿名函数,因为我需要传递一个额外的参数清理方法。 在清理期间,我没有得到一个函数处理程序,因为我使用的是匿名函数。

只要在挂钩时保留对侦听器的引用,就可以检查它是否在emitter.listeners(eventName)返回的侦听器数组中。

粗糙的例子(我相信它可以更有效率)

 /** * Created by cool.blue on 8/4/2016. * http://stackoverflow.com/q/38700859/2670182 */ const EE = require('events'); const util = require('util'); var host = new EE(); // set up a emitter with n events const n = 10; const events = Array.apply(null, Array(n)).map((x, i) => 'event_' + i); events.forEach(function(e){ host.on(e, function g() {console.log(e)}) }); console.log(util.inspect(host)); // get a reference to one of the listener functions const target = 'event_3'; var probe = host.listeners(target)[0]; // add a method to only add unique listeners host.onUnique = function (type, listener){ var slot = this.listeners(type).find(function(l) { return l === listener }); if(slot) return this; console.log('adding'); return this.on(type, listener) }; // try to add the same listener again var count0 = host.listenerCount(target); var count1 = host.onUnique(target, probe).listenerCount(target); console.log('added ' + (count1 - count0) + ' listeners'); // added 0 listeners console.log(util.inspect(host)); // try to add a new listener count0 = host.listenerCount(target); count1 = host.onUnique(target, function h(){ console.log('different cb')}).listenerCount(target); console.log('added ' + (count1 - count0) + ' listeners'); // added 1 listeners console.log(util.inspect(host)); 

为了回应更新的问题…

你可以做这样的事情…

TL; DR

其基本思想是为侦听器使用非匿名函数,并传递对它的引用以及与外部作用域中的效用函数的连接。

 const EE = require('events'); const util = require('util'); (function manage(host){ host.name = 'host'; host.release = function(){ console.log('released!') }; function l(err) { onErr(err, host, l) } le = 'error'; host.on('error', l); if(Math.random() > 0.5) host.emit('error', new Error('oops!')); if(le) cleanUp(host, l, 'manage'); })(new EE()); function onErr(e, h, l) { console.error(`\n${h.name}: ${e.message}`); h.release(); cleanUp(h, l, 'onError') } function cleanUp(h, l, context){ console.log('\n\x1b[33m' + context + '\n' + 'before:\t' + h._eventsCount + '\x1b[0m\n' + util.inspect(h)); h.removeListener(le, l); console.log('\n\x1b[33mafter:\t' + h._eventsCount + '\x1b[0m\n' + util.inspect(h)); delete le } 

IIFE只是为了模拟在外部范围内没有对hostconnection )的引用的情况。