Code is not executed in the order

Hi,

I have a strange comportement with my code in Ionic : the code is not executed in the order.

In one function in my controller, i put several alerts to undesterand a bug, and an alert in the end of my method. The last alert is set before the alert I put at the start of my method when i test it. There is the code :
$scope.add = function()
{

$scope.final_d = $scope.transac.dat; //Finale date with date and hours from the form
$scope.final_d.setHours($scope.transac.ho.getHours());
$scope.final_d.setMinutes($scope.transac.ho.getMinutes());
$scope.final_d =  $scope.final_d.getTime(); //Timestamp

//Update solde user
var query = "SELECT * FROM options WHERE name = 'solde'";
$cordovaSQLite.execute(db, query).then(function(res) {
    $scope.solde = parseFloat(res.rows.item(0).value);
    alert("Solde chargé : ");
    alert($scope.solde);

});

//Upadate sold people
query = "SELECT * FROM people WHERE id = ?";
$cordovaSQLite.execute(db, query, [$scope.choice.id]).then(function(res) {
    $scope.solde_people = res.rows.item(0).solde;
});



if ($scope.transac.type == 0) // User give money
{
    alert("Solde censé être chargé : ");

    alert($scope.solde);

    $scope.solde = $scope.solde + parseFloat($scope.transac.amount);

    alert("after addition with new value");
    alert($scope.solde);

    $scope.solde_people = $scope.solde_people + $scope.transac.amount;

}

The alert alert("Solde censé être chargé : "); is set before the alert alert("Solde chargé : ");

I wrote console.log instead of alert, and i have this…

app.js:214 Solde censé être chargé : 
app.js:216 0
app.js:220 after addition with new value
app.js:221 50
app.js:199 Solde chargé : 
app.js:200 0

The number of the lines is not coherent…

Therefore, my bug come from this comportement, because i use a var that depends from a precedent request who is made after i need it… Do you have any idea about this ?

I think the reason is that queries are asynchronous, so they do not execute the code immediately but wait for data and running next code at the same time. this: https://docs.angularjs.org/api/ng/service/$q will help you.

3 Likes

I think your sql query is taking time for execution that’s why your second alert is appearing before first.
You can use $timeout for your query till the execution done.

   app.controller('Ctrl_name', function($timeout){
        $timeout(function(){

         var query = "SELECT * FROM options WHERE name = 'solde'";
        $cordovaSQLite.execute(db, query).then(function(res) {
            $scope.solde = parseFloat(res.rows.item(0).value);
            alert("Solde chargé : ");
            alert($scope.solde);

        });

        }, 5000);
        });

Thanks, i will test with timeout, but is there any way to do it in another way, because sometimes, the timeout will not be enough (if my app have, for example, 1000000 lines in the database…), just in saying to the code : don’t execute until that is before you is finish ?

Do not under any circumstances use timeout for something like this!!!

You should look at @Adamxyz’s answer. Or just look at promises in general. You need to learn how asynchronous programming works. You’re using it in your code already but it’s clear you don’t understand it. Please read into it. Updated with code sample.

Put the following in something like sqlService.js

function getSoldeUserAndSoldPeople() {
    return $q.all({soldeUser: updateSoldeUser(), soldPeople: updateSoldPeople()});
}

function updateSoldeUser() {
  return $cordovaSQLite.execute(db, query).then(function(res) {
    return parseFloat(res.rows.item(0).value);
  });
}

function updateSoldPeople() {
  return $cordovaSQLite.execute(db, query, [$scope.choice.id]).then(function(res) {
    return res.rows.item(0).solde;
  });
}

Then back in your contoller do something like:

sqlService.getSoldeUserAndSoldPeople().then(doStuffWithData);

function doStuffWithData(res) {
  $scope.solde = res.soldeUser;
  $scope.solde_people = res.soldPeople;

  alert("Solde chargé : ");
  alert($scope.solde);

  if ($scope.transac.type == 0) { // User give money
  
     alert("Solde censé être chargé : ");
     alert($scope.solde);

     $scope.solde = $scope.solde + parseFloat($scope.transac.amount);

     alert("after addition with new value");
     alert($scope.solde);

     $scope.solde_people = $scope.solde_people + $scope.transac.amount;
  }
}

This is just a rough idea based on your code sample, please read about promises and $q.

2 Likes

another method is to use promises with $q constructor to execute your code.

$q constructor helps to run the function for asynchronous time and return the promises in the form of reject and resolve till your execution complete.

there is an exmple for how to use promises check this fiddle.
http://jsfiddle.net/softwaredoug/z58vmdnn/

1 Like

Reallly thanks for your helps.

I have read the documentation and i think I master better the $q, but not perfectly apparently, because i still have a bug that i reall don’t understand…

Here is my new code :

    function getSoldeUserAndSoldPeople(choice, id) {


        return $q.all({soldeUser: getSoldeUser(choice), soldPeople: getSoldPeople(id)});
    }

    function getSoldeUser(choice) {
        var query = "SELECT * FROM options WHERE name = ?";
        return $cordovaSQLite.execute(db, query,[choice]).then(function(res) {
            return parseFloat(res.rows.item(0).value);
        });
    }

    function getSoldPeople(id) {
        var query = "SELECT * FROM people WHERE id = ?";
        $cordovaSQLite.execute(db, query, [id]).then(function(res) {
            alert("in the matrice");
            return res.rows.item(0).solde;
        });
    }

Controller :

            getSoldeUserAndSoldPeople($scope.cho, $scope.choice.id).then(function(res)
            {
                $scope.solde = res.soldeUser;
                $scope.solde_people = parseFloat(res.soldPeople);
                alert("réel");

            console.log(res.soldPeople);

            if ($scope.transac.type == 0) // User give money
            {
                $scope.solde = $scope.solde + parseFloat($scope.transac.amount);
                $scope.solde_people = $scope.solde_people + parseFloat($scope.transac.amount);

                //Update solde user
                query = "UPDATE options SET value = ? WHERE name = 'solde_pos'";
                $cordovaSQLite.execute(db, query, [$scope.solde]);

            }

            else {
                //User owe money
                $scope.solde = $scope.solde - parseFloat($scope.transac.amount);
                //People give money

                $scope.solde_people = $scope.solde_people - parseFloat($scope.transac.amount);

                //Update solde user
                query = "UPDATE options SET value = ? WHERE name = 'solde_neg'";
                $cordovaSQLite.execute(db, query, [$scope.solde]);
            }

This three lines in my controller
$scope.solde = res.soldeUser;
$scope.solde_people = parseFloat(res.soldPeople);
alert(“réel”);

are after the .then. However, the alert("réel’) is set BEFORE the alert(“in the matrice”); and the value returned by getSoldPeople is undefined … It look like exaclty like before.

But in this case, with the $q.all, the code shouldn’t be executed before getSoldeUser(choice) and getSoldPeople(id) are finish, right ?

1 Like

Hey looking good this is a big improvement! I believe your problem is that $q.all expects each value in the object passed in to be a promise, but because you are not returning a promise in getSoldPeople it’s not working properly. You need getSoldPeople to look like getSoldeUser above and actually return the promise itself like this:

function getSoldPeople(id) {
    var query = "SELECT * FROM people WHERE id = ?";
    return $cordovaSQLite.execute(db, query, [id]).then(function(res) {
        alert("in the matrice");
        return res.rows.item(0).solde;
    });
}

Notice the return before the $cordovaSQLite.execute. This way the promise itself is returned from the function, which is what $q needs. Good work on updating your code. :thumbsup:

1 Like

Yes, it was that! Thanks ! :thumbsup: