Hello to everyone! Today I thought of sharing what I have got to know about Node.js – Callback functions.
As mentioned earlier node is largely based on event-driven programming. Event-driven programming is determining the applications flow based on events and state changes. We need to have a system to keep listening to any events being raised and then fire a callback functions based on that. With that we can talk about the node’s Eventloop: the eventloop constantly keeps on listening for event coming from the server side. They can be external events such as HTTP requests/TCP connections or they can be internal operations such as timers. The important point is that these are all handled as individual events in node, also they are more likely to interlace. Node does not wait for an event to complete, it just reacts to the events as they arrive. This is why node can be called ‘single-threaded’. This non-blocking nature of node, is what makes it different from other traditional server side languages that requires the programmer to manage multiple threads.
To write code with the non-blocking asynchronous ways of node, there is a special mechanism called function callbacks.
To explain callback functions, I am going to describe a scenario from an application me and my team developed sometime back: We were going to delete a user by their user name and then delete any vehicle(s), that have been added under that person. Users and UserVehicles were in two separate mongoDB collections. In this specific scenario, first the user is searched and if the user exists, that record is deleted, then if only that action succeeds, the vehicles are deleted. (I am sure there might be other ways to get this done, but this is how it was implemented in this application). It is not possible to nest queries in mongoDB, because mongo shell is just an interactive JS interface to MongoDB server. Therefore in order to delete vehicles a separate method was required. But when that separate method was invoked to delete the vehicles, the main method completed its flow, before the vehicles got deleted. This was because of node.js’s eventloop we spoke about earlier.
As a solution for this, a callback method was implemented:
Note – For the purpose of this blog, I am going to insert a snippet of code from the same application (Please ignore the red lines in the code, since I extracted only these two methods to a typescript file)
In the above code, REST API was used to call the delete method.
In Image 1, ‘deleteVehicles’ method takes two parameters, one is the user name and the second one is the callback function. In this case the callback has been written as an anonymous function. What happens here is when the vehicle deleting process is completed, the result was passed to the mentioned anonymous function. By this way node.js is free to execute other code, while waiting for the results. By the use of callbacks the code will run asynchronously. The ‘deleteVehicle’ method in Image 2 accepts the callback function as an argument, therefore after executing the vehicle deleting queries, it will invoke the callback function with the success/failure of the query execution.
There are several conventions to follow when implementing callback functions in node.js:
- Callback function is the last parameter in asynchronous function call.
- Error is the first parameter to the callback function
- As I have done in the above sample, writing the callback as an anonymous function is better, otherwise there will be many callback function written, that are only used once. Another advantage of writing anonymous functions is that, all the variables in the method are available throughout the logic of the scenario.
I hope this will not confuse anyone. Thank you for reading this blog.
for the best!!