Paul Paul - 4 months ago 61
AngularJS Question

Angular promise hangs UI

My app hangs even though I am using a promise to run calculations.

I'm writing a little BlackJack game in Angular. In this game, I want to display permutations of cards at the bottom of my game board. My game board renders fast when I don't call the

getData()
method (see below) that calculates the permutations. But when I call
getData()
my UI hangs.

The service where I declare and return a promise looks like this:

app.service('cardService', ['$q', 'myservice', 'calculation', function ($q, myservice, calculation) {
return {
getData: function () {
var defer = $q.defer();

myservice.setup_deck();
var cards = myservice.get_needed_cards(myservice.player_hand, myservice.static_deck);

// This is calculation-intensive
var dh_grouped = calculation.step1(cards);
var result = calculation.step2(dh_grouped);

defer.resolve(result);

return defer.promise;
}
};

}]);


Now, I call the promise in a very vanilla way like this:

// controller.js
$scope.display_calculations = function () {

cardService.getData().then(function(result){
$scope.calcs = result;
console.log('calculations successful');
});
console.log('this message shows before the one above');
};

// The relevant HTML
<td ng-repeat="c in calcs">{{c.result}}</td>


To debug, I removed the statement
$scope.calcs = result
to see if removing them would stop my UI from hanging:

cardService.getData().then(function(result){
console.log('calculations successful');
});


The above did not work. My UI still hangs! The only way I could prevent the UI from hanging is by not calling
getData()
.

How can I use angular so my expensive operations don't hang the UI?

P.S. I am using Angular 1.2.21 and even tried using 1.5.x but that did not work either.

Answer

Use $timeout

app.service('cardService', ['$q', '$timeout', 'myservice', 'calculation', function ($q,  $timeout, myservice, calculation) {
    return {
        getData: function () {
            return $timeout(function() {
               myservice.setup_deck();
               var cards = myservice.get_needed_cards(myservice.player_hand, myservice.static_deck);

               // This is calculation-intensive
               var dh_grouped = calculation.step1(cards);
               return calculation.step2(dh_grouped);
            }, 1);
        }
    };
}]);

This will defer the execution and let your UI load first. $timeout returns a promise so the rest of your code can stay the same.