How to emit event in mongoose middleware?
Asked Answered
H

2

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?

Headman answered 1/6, 2015 at 9:22 Comment(0)
S
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.

Sybarite answered 1/6, 2015 at 13:1 Comment(4)
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.Headman
@Headman 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.Laguna
@AaronDufour then how can I pass eventEmitter in my model to app.js?Headman
@Headman You would have to export it from the model file and require it from app.js.Laguna
G
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);
})
Gertrudegertrudis answered 9/6, 2015 at 20:23 Comment(3)
Did you try your method, I did and its not working.this.schema is undefined.Headman
Sorry, I didn't test with the post hooks but I know it works if you have an instance of document. So you can just replace this.schema by blog.schema. It should workGertrudegertrudis
@paynestrike, did you succeed in making the notification work?Gertrudegertrudis

© 2022 - 2024 — McMap. All rights reserved.