2012-08-16 27 views
0

我在node-mongodb-native和EventEmitter之間有一個奇怪的問題。mongodb和EventEmitter之間的問題

我已經減少了問題的代碼:

var mongodb = require('mongodb'), 
    Server = mongodb.Server, 
    Db = mongodb.Db, 
    events = require('events').EventEmitter.prototype; 

// Create a mongo client object 
var client = new Db('tartempion', 
    new Server(
     '127.0.0.1', 
     27017 
    ) 
); 

// Open the connection 
client.open(function(err, db) { 
    if (err) throw err; 
    database = db; 
    console.log('Database driver loaded.'); 
    events.emit('hi'); 
}); 

// If I comment this out, I don't get the error anymore 
// and the "Database driver loaded." log is displayed. 
events.on('hi', function() { 
    console.log('hey man'); 
}); 

而且我得到這個錯誤:

net.js:140 
    // Uncomment the following lines after libuv backend is stable and API 
    ^
RangeError: Maximum call stack size exceeded 

我認爲這可以在回調中涉及到的事件,但這代碼作品:

events.on('hi', function() { 
    console.log('hey man'); 
}); 

f(function() { 
    events.emit('hi'); 
}); 

function f(callback) { 
    callback(); 
} 

所以......我沒有看到問題出在哪裏。

只是FYI,我交叉在node-mongodb-native issue queue上發佈這個。

回答

2

你必須定義eventsEventEmitter一個實例,而不是僅僅在EventEmitter.prototype對象的引用:

var ..., 
    EventEmitter = require('events').EventEmitter, 
    events = new EventEmitter; 

或被視爲由EventEmitter.prototype繼承的對象:

var ..., 
    events = Object.create(require('events').EventEmitter.prototype); 

你只有得到一個EventEmitter.prototype每運行node.exe(因爲require('events')的結果被緩存),所以使用它作爲實例可以修改通過使用的每個實際實例對核心節點API以及像mongodb這樣的第三方模塊。


由於Brandon suggested,如果你需要訪問例如在2個模塊,第3模塊中定義它:

// emitter.js 
var EventEmitter = require('events').EventEmitter; 
module.exports = new EventEmitter; 
var ..., 
    events = require('./emitter'); 
+0

好了,問題是,我想在兩個不同的文件來利用此事件,所以我不能實例化一個對象,因爲它不會是同一個對象在這兩個文件中。這就是爲什麼我想使用EventEmitter的原型。但是,爲什麼我需要*在沒有實例化的情況下實例化它? (見例子)。 – 2012-08-16 19:11:41

+1

MongoDB包或其依賴關係中的其他庫或模塊可能取決於EventEmitter,我的猜測是它們遇到了問題,因爲您正在通過附加事件處理程序等來破壞它的原型。如果你需要在多個文件中使用同一個對象,[make a module](http://nodecasts.net/episodes/3-modules),不要使用原型。 – 2012-08-16 19:19:09

+1

@FlorianMargaine如果你的意思是你的第二個代碼片段,那麼你不用創建一個實例,因爲你沒有使用任何其他實例 - 比如''mongodb.Db',[從EventEmitter繼承](https:// github。 COM/mongodb的/節點mongodb的天然/斑點/ V1.0.2/LIB/mongodb的/ db.js#L217)。 – 2012-08-16 19:48:20

3

如果你說:

events = require('events').EventEmitter.prototype; 
event.on('foo'); 

你正在尋求麻煩,因爲然後EVERY事件對象會得到這個綁定(因爲你甚至把它寫入基本原型TS)...

這是更好的(如喬納森說)實例在其綁定您的活動一個新的對象......

sharedEventEmitter.js

var events = require('events'); 
var eventEmitter = new events.EventEmitter(); 
module.exports = eventEmitter; 
從其餘

現在你的項目 - 你可以把它看作是一個單身人士 - 一個會將事件發送到任何事情上的對象 - 每次你需要('sharedEventEmitter')你得到相同的實例(它是一個單身人士):

a.js

var sharedEvents = require('./sharedEventEmitter'); 
sharedEvents.on('foo', function(st){ 
    console.log(st); 
}) 

b.js

var sharedEvents = require('./sharedEventEmitter'); 
sharedEvents.emit('hello from another file'); 
+0

感謝你的想法,這是我最後去的。僅供參考,發佈的事件在您的示例中沒有任何監聽器:p。 – 2012-08-16 21:44:27