Question

I have the following condition where syncAnalytics is called first. Inside this function, there is another function, retreiveAnalyticsData, written to retrieve the locally stored data.

But before the value is returned from retreiveAnalyticsData, the rest of function syncAnalytics gets executed.

DemoModule.factory('ApplicationAnalytics', function ($http, $location, DBO) {
    return {
        syncAnalytics: function () {
            console.log("syncAnalytics called");// Getting displayed 1st
            // Retrieve analytics data available data from db
            var inputData = this.retreiveAnalyticsData();
            console.log("Input Data : " + JSON.stringify(inputData)); // Getting displayed 4th
        },    
        retreiveAnalyticsData: function () {
            console.log('retreiveAnalyticsData called');// Getting displayed 2nd
            // Select all rows from app_analytics table in db
            var selectQuery = "SELECT * FROM app_analytics";
            var analyticsData = [];
            DBO.execQry(selectQuery, function (results) {
                var len = results.rows.length,
                    i;
                for (i = 0; i < len; i++) {
                    analyticsData.push(results.rows.item(i).text);
                }
                console.log(analyticsData); //Getting displayed 5th
                return analyticsData;
            });
            console.log('retreiveAnalyticsData ended');// Getting displayed 3rd
        }
    };
});

So basically :

var inputData = this.retreiveAnalyticsData(); //This should be executed before the below line.
console.log("Input Data : " + JSON.stringify(inputData)); // Getting displayed 4th

Any insight will be greatly appreciated.

Note : I am using AngularJS

Was it helpful?

Solution

DBO.execQry is an asynchronous function. You may see this because of the callback pattern - e.g. the second paramter of execQry is a function that is called if execQry is ready retrieving the data. I guess what you see is, that console.log('retreiveAnalyticsData ended'); is printed out before console.log(analyticsData);

How to handle this?

1) The oldschool way would be using a callback function:

syncAnalytics: function () {
   this.retreiveAnalyticsData(function(inputData){
      console.log("Input Data : " + JSON.stringify(inputData)); 
   });
}, 

retreiveAnalyticsData: function (callback) {
   var selectQuery = "SELECT * FROM app_analytics";
   var analyticsData = [];
   DBO.execQry(selectQuery, function (results) {
      var len = results.rows.length,
      for (var i = 0; i < len; i++) {
         analyticsData.push(results.rows.item(i).text);
      }
      callback(analyticsData);
   });
}

But this way has a lot of disadvantages. What if you would like to handle erros or need to to make multiple asynchronous calls or sync them together? So we came to the promise pattern.

2) The Promise Pattern by $q

syncAnalytics: function () {
   this.retreiveAnalyticsData().then(function(inputData){
         console.log("Input Data : " + JSON.stringify(inputData)); 
   });
}, 

retreiveAnalyticsData: function () {
   var selectQuery = "SELECT * FROM app_analytics";
   var analyticsData = [];
   var deferred = $q.defer();
   DBO.execQry(selectQuery, function (results) {
      var len = results.rows.length,
      for (var i = 0; i < len; i++) {
         analyticsData.push(results.rows.item(i).text);
      }
      deferred.resolve(analyticsData);
   });
   return deferred.promise;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top