11

I want to emit event when new blog saved

blog.post('save',function(blog){
    this.emit('newBlog',blog)
})

and somewhere else in my project say app.js can listen this event

EventEmitter  = require('events').EventEmitter;
emitter = new EventEmitter();

emitter.on('newBlog',function(blog){
    console.log(blog);
})

how to do this?

paynestrike
  • 4,348
  • 14
  • 46
  • 70

2 Answers2

9

The way event emitter works is that you have to use the same event emitter object to listen on that you used to emit. So you need something like this:

To share this among different parts of your project you should create a module out of it and require it wherever needed.

my-event.js:

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

Then you require this eventEmitter wherever you want to use it

blog.js:

var myEvent = require('../my-event');
blog.post('save',function(blog){
    myEvent.emit('newBlog', blog);
});

app.js:

var myEvent = require('./my-event');
myEvent.on('newBlog', console.log);

If you don't want to go through the trouble of creating and requiring your own module, you can use the global process which is also an EventEmitter.

anywhere:

process.on('my-custom-event', myCustomHandler);

anywhere-else:

process.emit('my-custom-event', data);

Although a fair warning: you're polluting the global scope. If some other module is also doing the same and using the same event names then you have a conflict which may surface in unexpected manner and be even harder to debug.

laggingreflex
  • 32,948
  • 35
  • 141
  • 196
  • I think mongoose schema inherit from EventEmitter, so I can just do `this.emit('newBlog',blog)` instead of `eventEmitter.emit('newBlog',blog);`,but the event listener won't work. and I think if I have to pass the same event emitter whenever i need to use it , then what is the point? I can just replace event with actual business logic to save me a bunch of trouble. – paynestrike Jun 02 '15 at 02:53
  • 1
    @paynestrike The point is decoupling. It means that the thing that is emitting doesn't have to know about all of the things that are listening. – Aaron Dufour Jun 04 '15 at 04:39
  • @AaronDufour then how can I pass eventEmitter in my model to app.js? – paynestrike Jun 04 '15 at 07:53
  • @paynestrike You would have to export it from the model file and require it from app.js. – Aaron Dufour Jun 04 '15 at 13:53
4

If you emit your event from an document (an instance of a specific Schema), then you must listen on this instance to receive the event.

If you want to listen globally on all events generated by all instances then you must emit the event from the Schema.

blog.post('save',function(blog){
    blog.schema.emit('newBlog',blog)
})

And in your app.js for example, you can listen for events on the schema:

Blog.schema.on('newBlog',function(blog){
    console.log(blog);
})
Julien Bachmann
  • 753
  • 8
  • 18