2016-08-01 55 views
2

有沒有方法檢查node.js中的對象是否已存在偵聽器? 我要實現以下情形:如果偵聽器尚未添加並且偵聽器處理程序是匿名函數,那麼在nodeJS中添加偵聽器

  • 獲取DB
  • 的對象做一些操作
  • 添加聽衆如錯誤,因此,如果相同的偵聽器尚未添加[假設排水等所有的操作聆聽者操作是相同的]

我想優化添加偵聽器的方式,如果我們嘗試並添加現有的偵聽器,將不會添加新的偵聽器。節點文檔說「沒有檢查是否已經添加了監聽器。多次調用傳遞相同的eventName和listener組合將導致監聽器被多次添加和調用。」

有辦法解決它嗎?
[編輯] -Adding一些示例代碼

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); 
    }; 

連接將包含一個分貝連接並從外部package.In其未來的發言connection.on( '錯誤',函數(ERR){onErr(ERR ,連接);});我使用一個匿名函數,因爲我需要傳遞一個額外的參數到清理方法。在清理過程中,我沒有得到函數的處理函數,因爲我使用的是匿名函數。

+0

只需檢查[當前綁定到特定事件的偵聽器](https://nodejs.org/docs/latest/api/events.html#events_emitter_listeners_eventname)以查看是否存在您要添加的偵聽器。使用'emitter.listeners(eventName)'。 –

+0

@CoolBlue:我如何檢查被util.inspect綁定的監聽器的名稱?它回送輸出爲:「添加的監聽器是[[Function], {[Function:g]監聽器:[Function]}, [功能], [功能]]」 – gkurian

+0

只需使用對監聽器的引用函數檢查'emitter.listeners(eventName)'返回的偵聽器數組。見下面的答案... –

回答

1

只要您在掛鉤時保留對偵聽器的引用,就可以檢查它是否位於由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) 
    } 
    l.e = 'error'; 

    host.on('error', l); 

    if(Math.random() > 0.5) 
     host.emit('error', new Error('oops!')); 

    if(l.e) 
     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(l.e, l); 
    console.log('\n\x1b[33mafter:\t' + h._eventsCount + '\x1b[0m\n' + util.inspect(h)); 
    delete l.e 
} 

的IIFE只是模仿你的情況沒有在外部範圍沒有提及hostconnection)。

+1

Thankx爲您的片段,我提出了一個解決方案結合這兩個。對於遲到的迴應抱歉! – gkurian