wuno
wuno

Reputation: 9875

Passing Data Through Call Back Functions When it Is In Scope

Background

My issue is understanding a scope and how to use callback functions appropriately. I can not seem to string the events along in order as I try to plan. I have had trouble reading posts and relating them to my current problems. I guess what I really do not get is how to implement the logic.

Question

I have a few scenarios that are causing me problems in my application. They all revolve around a situation where I need data which is not in scope yet. But the function already has a callback function.

Example

This function inserts data into a database.

   updateProfile: function (req, res) {
    pool.getConnection(function (err, connection) {
        var email = req.body.email;
        var sql = 'INSERT INTO rw_users SET email = ?';
        var params = [email];

        connection.query(sql, params, function (err, results, fields) {
            if (err) {
                res.status(500).send();
                throw err;
            }
            connection.release();
        });
    });
},

This next function needs the ID from the user which was just created.

 createCustomerProfile: function (email, id) {
            merchant.createCustomerProfile(email, id, function callback(merchantRes){
                    pool.getConnection(function (err, connection) {
                var sql = 'UPDATE rw_user SET auth_customer_id = ? WHERE email = ?';
                var params = [merchantRes, email];
                connection.query(sql, params, function (err, results, fields) {
                    if (err) {
                        throw err;
                    }
                    console.log('new customer created at authorize.net');
                });
            });
          });
        }, 

In the function updateProfile() I am creating a new user in my database. In the second function createCustomerProfile() I need the ID of the newly created user that was entered in function one.

Please show me a way to handle functions like this. Where I need the data from the first process so I can use it in the second function. This gets worst as it goes on because when function two is complete it will have a new customerID in its response from the API call it makes. That response also needs to make another database query to update the row with its ID. Then once these 2 functions are done I need to query the database again to return the whole row.

To break this down,

  1. Create the user in the database.
  2. Using the id and email of the new user created in function 1. A new customer account id with authorize.net api gets created in function 2.
  3. Insert the new customer id from the response of the authorize.net API into the new user row that was created in function one.
  4. Return the whole row.

My question to be clear. What is a possible solution to use to be able to take tasks like in my list and clearly implement them to be dealt with in order so I can use the response from each one when it exists in scope?

Upvotes: 0

Views: 92

Answers (1)

Mia
Mia

Reputation: 184

The easiest way to implement your program is to use nested callbacks but this easily becomes messy and hard to maintain your codes. We can use promises or generators for doing this in more elegant way. First of all, let's have a look at the following codes (simple one).

     const test1= () => {
         return new Promise((resolve,reject)=>{
              setTimeout(function(){ <-- async operation
                 resolve(10);
             })
         })
     }

     const test2= (data) => {
         return new Promise((resolve,reject)=>{
                    setTimeout(function(){ <-- async operation
                         resolve(data+20)
                    })
                })
     }

     test1()
     .then(test2)
     .then((finalData)=>{console.log(finalData)});

This will give us value 30. So how does this work. Both test1 and test2 return promise object which has a method name 'then'.

   new Proimse((resolve,reject)=>{ async operation comes here , when the operation 
done successfully , we resolve it, otherwise reject , })

The then method expecting a function and we can pass the parameter through resolve function. But only one parameter is expected, so if more than one parameter are needed, objects or arrays are needed. If you can understand the codes above, let's refactor you codes a bit

     getConnection:function(req,res){
           return new Promise((resolve,reject)=>{
                 pool.getConnection(function (err, connection) {
                        if(err) return reject(err);
                        resolve({connection,req,res});
             });
             })
     },

     updateProfile:function(obj){
         const { connection,req,res } = obj;
         return new Promise((resolve,reject)=>{
             var email = req.body.email;
             var sql = 'INSERT INTO rw_users SET email = ?';
             var params = [email];
             connection.query(sql, params, function (err, results, fields) {
                     if (err) return reject(err);
                     resolve({email,results,connection});
             });
         })
     },

     createCustomerProfile: function (obj) {
                   const { email,results,connection } = obj;
                     return new Promise((resolve,reject)=>{
                         merchant.createCustomerProfile(email, results.id, function callback(merchantRes){
                                 var sql = 'UPDATE rw_user SET auth_customer_id = ? WHERE email = ?';
                                 var params = [merchantRes, email];
                                 connection.query(sql, params, function (err, results, fields) {
                                         if (err) {
                                                 throw err;
                                         }
                                         console.log('new customer created at authorize.net');
                                         connection.release();
                                 });
                     });
                     })
  }

    yourModule.getConnection(req,res)
              .then(yourModule.updateProfile)
              .then(yourModule.createCustomerProfile)
              .catch((err)=>{console.log(err)})

Now you need to modify this code so that is works with your module.

Upvotes: 1

Related Questions