I'm working on a project where I have a Feeds page which shows all type of post by all users. Type specific list page and Posts' detail page.
Pages- 1. Feeds 2. List (Type specific) 3. Detail (detail of a post)
So I have following Mongo collection - 1. Feed 2. type1 post 3. type2 post 4. type3...
Now when a user post a new Post I save it to respective collection lets say to 'type1 post' and return success to browser. But I also want to update my 'Feed' collection with same data. I don't want it to be done before response is send. Because that will increase User's wait time. Hence I have used Events. Here's my code -
const emitter = new event.EventEmitter();
function savePost(){
// Code to save data to Mongo collection
emitter.emit('addToFeeds', data);
console.log('emit done');
return res.json(data);
}
emitter.on('addToFeeds', function(data){
// code to save data to Feeds collection
console.log('emitter msg - ', data);
});
Now when I check the console.log output, it shows "emitter msg -" first and then "emit done". That's why I'm assuming emitter.on code is executing before res.json(data);
Now I'm wondering does Events are blocking code? If I have to update Feeds in background or after response is sent what is the right way? In future I also want to implement caching so I also have to update cache when even a post is added, that too I want to do after response is sent or in background.
Yes, events are synchronous and blocking. They are implemented with simple function calls. If you look at the eventEmitter code, to send an event to all listeners, it literally just iterates through an array of listeners and calls each listener callback, one after the other.
Now I'm wondering does Events are blocking code?
Yes. In the doc for .emit(), it says this: "Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each."
And, further info in the doc in this section Asynchronous vs. Synchronous where it says this:
The EventEmitter calls all listeners synchronously in the order in which they were registered. This is important to ensure the proper sequencing of events and to avoid race conditions or logic errors. When appropriate, listener functions can switch to an asynchronous mode of operation using the setImmediate() or process.nextTick() methods:
If I have to update Feeds in background or after response is sent what is the right way?
Your eventListener can schedule when it wants to actually execute its code with a setTimeout()
or a setImmediate()
or process.nextTick()
if it wants the other listeners and other synchronous code to finish running before it does its work. So, you register a normal listener (which will get called synchronously) and then inside that, you can use a setTimeout()
or setImmediate()
or process.nextTick()
and put the actual work inside that callback. This will delay running your code until after the current Javascript that triggered the initial event is done running.
There is no actual "background processing" in node.js for pure Javascript code. node.js is single threaded so while you're running some Javascript, no other Javascript can run. Actual background processing would have to be done either with existing asynchronous operations (that use native code to run things in the background) such as network I/O or disk I/O) or by running another process to do the work (that other process can be any type of code including another node.js process).