0

I have list which is filled in for cycle where I calling assync function by thos way:

In For cycle I'm calling

  row.SUCCES_RATE_SINCE = $scope.computeSuccessRateSinceStart(row);

Called function

  // Calculate percentage of a whole from since
    $scope.computeSuccessRateSinceStart = function(row) {

        db = window.sqlitePlugin.openDatabase({name:"callplanner"});
        // GET APPT COUNT
        db.transaction(function(tx) {
        tx.executeSql(sqlQuery, [], function(tx,results){
            // init empty array for results
            for (var i=0; i < results.rows.length; i++){
                row = results.rows.item(i);
                //Udpate date for writeout
                //row.DATE = moment(row.DATE).format('ddd DD.M');
                console.log("row APPT count is " + JSON.stringify(row));
                apptCnt = row.APPT_CNT;
                convCnt = row.CONVERS_CNT;
                dailySuccessRateSince = apptCnt / convCnt * 100;
                console.log("Success rate since is " +dailySuccessRateSince);
                // THIS IS NOT WORKING
                return Math.round(dailySuccessRateSince);

            }
            });
        },function (e) {
                console.log("ERROR: " + e.message);
                $ionicLoading.show({
                    template: $translate.instant('ERROR_DATABASE'),
                    duration:1000
                });
        });

    };

Problem is that computed value is always returned null (return function is executed before value is available in scope).

I'm quite new in Angular but i found that this issue could be solved using promises. Could somebody give me the example how to return value properly?

Many thanks for any help.

EDIT:

Called method is now triggered, but i cannot pass returned value into variable like this:

var test = $scope.computeSuccessRateSinceStart(row).then(function(result){
     //ALERT WITH VALUE WORKS FINE
     alert("Result " + result);
     return result;
    });
    // THIS GIVES ME EMPTY ARRAY {}
    alert("Result " + JSON.stringify(test));
5
  • Not even promises allow you to return the value - it still would be asynchronous. You could return a promise for the value, though. Commented Oct 8, 2014 at 12:00
  • Could You please add some example based on my code? I tried a few tutorials but without luck. Commented Oct 8, 2014 at 12:03
  • Mohammad's answer covers it quite well (I've edited it for a bit clarity). And NO, it is outright impossible to pass the "returned value" into a variable, because your code is asynchronous. Do everything in the callback! Commented Oct 8, 2014 at 13:53
  • Could You add some example of "Do Everything in callback" please? Because in for cycle are called some other functions which are assync too. Commented Oct 8, 2014 at 16:14
  • What for cycle? Yes, make that loop a recursive function and call the next step from the callback. Commented Oct 8, 2014 at 16:16

1 Answer 1

2

Why don't you just make your method such that it always returns a promise, and then extract the result from the promise?

$scope.computeSuccessRateSinceStart = function(row) {
    var deferred = $q.defer();

    db = window.sqlitePlugin.openDatabase({name:"callplanner"});
    // GET APPT COUNT
    db.transaction(function(tx) {
        tx.executeSql(sqlQuery, [], function(tx,results){
            // init empty array for results
            for (var i=0; i < results.rows.length; i++){
                row = results.rows.item(i);
                //Udpate date for writeout
                //row.DATE = moment(row.DATE).format('ddd DD.M');
                console.log("row APPT count is " + JSON.stringify(row));
                apptCnt = row.APPT_CNT;
                convCnt = row.CONVERS_CNT;
                dailySuccessRateSince = apptCnt / convCnt * 100;
                console.log("Success rate since is " +dailySuccessRateSince);
                // THIS IS NOW WORKING:
                deferred.resolve(Math.round(dailySuccessRateSince));
            }
        });
    }, function(e) {
        console.log("ERROR: " + e.message);
        deferred.reject(e);
    });

    return deferred.promise;
};

Usage:

$scope.computeSuccessRateSinceStart(row).then(function(result){
    // THIS GIVES THE VALUE:
    alert("Result " + JSON.stringify(test));
    return result;
}, function(e) 
    $ionicLoading.show({
        template: $translate.instant('ERROR_DATABASE'),
        duration:1000
    });
});
Sign up to request clarification or add additional context in comments.

4 Comments

Is it intentional that you didn't fix the problem in your code?
If you mean the line below:// THIS IS CALLED WHEN DATA ARE NOT AVAILABLE Where The promise is being resolved regardless of what happened before it, Yes. I thought it's not relevant to the main issue of handling async tasks, but yea, that line shouldn't be there.
@redrom The idea is to return a promise or a callback if you're performing an async task. Tbh I don't know how many async calls there are in the code you posted, Try the code in my answer now, I removed that problematic line Bergi mentioned.
Seems to be triggered right now, but i still cannot pass returned value into variable, please see my updated question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.