Skip to content

Instantly share code, notes, and snippets.

@siddrc
Last active December 13, 2018 15:41
Show Gist options
  • Save siddrc/c944efaacadc5cbda7b1f433631a50aa to your computer and use it in GitHub Desktop.
Save siddrc/c944efaacadc5cbda7b1f433631a50aa to your computer and use it in GitHub Desktop.
Revision Notes

Callback methods:

terminator-ill-be-back-arnold-meme

Yes I am a terminator fan...haha

ok coming down to nerdy talks.

Firstly from the name "Callback methods" itself, it is as if saying:

"I am going somewhere else now to do something else entirely different but a neccessity to complete this task, and I will be back with results and use it to resume and complete the flow ahead."

Here the neccessity is to interact with port 27017 and get a connection object from the mongodb service running at that port.

The I here is the main execution thread, as seen in the below code, when the .connect is encountered, it signifies that you are trying to do something out of the bounds of your application logic, or you are trying to gain access to a resource which can be given to you by the OS or something else beyond the control of your application. In this case you are trying to gain access to some service running @ 27017.

   mongodb.connect("mongodb://localhost:27017", function(error, connection) {
               //something block of code.
           })

As you don't actually know when this task will be done, you supply the method with a call back function, which means once you get the connection come back here and execute this block of code.

   mongodb.connect("mongodb://localhost:27017", function(error, connection) {
               //handle error
               //handle connection
               crudHandler(connection, crudParams)
           })

The mechanism of callback comes from the fact that, in Javascript a function can accept another function as an argument. Higher order functions.

Which also means that any running function can call another function either supplied as an arguement or kept inside a json and json is given in the argument, like in our case:

function crudOperations(crudHandler, crudParams) {
           mongodb.connect("mongodb://localhost:27017", function(error, connection) {
               crudHandler(connection, crudParams)
           })
       }    

Here the running function is crudOperations which takes 2 args: crudHandler and crudParams crudHandler actually points to some function which will execute "as a function but placed inside a callback function",during actual code execution. crudParams this is our json object which has some functions hidden inside , like this:

function crudOperations(crudHandler, crudParams) {
          mongodb.connect("mongodb://localhost:27017", function(error, connection) {
             if(error)
                 crudParams.errorCallback(error);//we can supply an error callback, just to handle errors
              else   
                 crudHandler(connection, crudParams)
          })
      }    

Here above the .errorCallback will run as function but placed inside the callback function. Please note all the code above is like a plan , which will work only if the supplied argument (createParams) contains the mentioned keys, will elaborate this below.

Moving on:

class Database {
    constructor() {
        this.create = function(createParams) {
            crudOperations(createHandler, createParams)
        }
        function crudOperations(crudHandler, crudParams) {
            mongodb.connect("mongodb://localhost:27017", function(error, connection) {
                if(error)
                   crudParams.errorCallback(error);//we can supply an error callback, just to handle errors
                else   
                   crudHandler(connection, crudParams)
            })
        }
        function createHandler(connection, createParams) {
            const db = connection.db(dbProperties.databaseName);
            const collection = db.collection(createParams.collectionName);
            collection.insert(createParams.payload, function(error, rowsAffected) {
                connection.close();
                if (error)
                    createParams.errorCallback(error);
                else
                    createParams.successCallback(rowsAffected)
            })
        }
    }/* other methods */
}
module.exports = Database;

As you can see above this points to Database instance,create is bound to this that means when an external party creates a instance of Database they can call create method using the (.) dot operator. The arguement needed for the method is one json object which needs to have the following json schema / plan: Please note unless the schema of the object passed to the instance of database, is not like this, it will not work as coded.

//JSON object
 {
                "collectionName": "FirstTable", //name of the collection
                "payload" : {name:"John Doe"}, //some json data object that needs to be inserted to the collection mentioned above.
                
                "successCallback": function(data) {
                    res.status(200).send(data);
                },//this function will be called if everything goes well.
                
                "errorCallback" : function(error){
                    res.status(500).send(error)
                }//this function will be called if anything fails.
 };

Here what we do is we weave the available rules and mould a logic that favors the flow that we want. Rules:

  1. Connect method needs a callback, it will perform the task of getting the connection and give us back two objects in the callback error and connection object.
  2. Here the point to our advantage is we can use this place as a placeholder and plug in the logic we want.
  3. A function can be passed to another function as an arguement.

Below is the user of Database.js

class HelloRouteHandler {
    static handle() {
        router.post("/", function(req, res) {
            const database = new Database();
            const insertParams = {
                "collectionName": "FirstTable",
                "payload" : {name:"John Doe"},
                "successCallback": function(data) {
                    res.status(200).send(data);
                },
                "errorCallback" : function(error){
                    res.status(500).send(error)
                }
            };
            database.create(insertParams)
        });
        return router;
    }
}
module.exports = HelloRouteHandler

As you can see HelloRouteHandler.js is:

  1. const database = new Database(); making a new instance of Database.js
  2. const insertParams = { "collectionName": "FirstTable", "payload" : {name:"John Doe"}, "successCallback": function(data) { res.status(200).send(data); }, "errorCallback" : function(error){ res.status(500).send(error) } }; making the object which will be later passed to the create method as an arguement.
  3. database.create(insertParams) finally calling the create method.

Here the only weird thing is the code hopping :(

  1. Only HelloRouteHandler.js has visibility to req and res and we need to send something back to user, whether the operation he requested was successfull 200 or did it fail 500 or 400 etc.HTTP Status Codes
  2. The only ticket to send something back is by using the res object.
  3. Hence we need to think-ahead in future,and code accordingly in your callback functions. Hence the neccessity of callbacks.

Additional Resources on how callbacks work

Link 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment