2016-07-21 3 views
1

Мое приложение зависает, хотя я использую обещание выполнить вычисления.Угловое обещание висит UI

Я пишу небольшую игру BlackJack в Angular. В этой игре я хочу отображать перестановки карт в нижней части моей игровой панели. Моя игровая плата быстро работает, когда я не вызываю метод getData() (см. Ниже), который вычисляет перестановки. Но когда я звоню getData(), мой пользовательский интерфейс зависает.

служба, где я заявляю и вернуть обещание выглядит следующим образом:

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; 
     } 
    }; 

}]); 

Теперь я называю обещание в очень ванильным образом, как это:

// 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> 

Для отладки, я удалил заявление $scope.calcs = result, чтобы увидеть, если удаление их остановит мой UI от подвешивания:

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

Вышеуказанный не работает. Мой пользовательский интерфейс все еще висит! Единственный способ, с помощью которого я мог предотвратить зависание пользовательского интерфейса, - это не позвонить getData().

Как я могу использовать угловые, чтобы мои дорогие операции не повесили интерфейс?

P.S. Я использую Angular 1.2.21 и даже пытаюсь использовать 1.5.x, но это тоже не сработало.

+0

Где и как часто вызывается display_calculations? Если пользовательский интерфейс зависает только из одного вызова, проблема не связана с угловым, а с общим JS.Дорогостоящие вычисления должны быть либо сделаны асинхронными, либо перемещены в веб-рабочий, чтобы не блокировать основной поток. – estus

+0

Да, я использовал $ timeout, и он работал как DerekMT ниже, и моя проблема исправлена. – Paul

ответ

2

Использование $ таймаут

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); 
     } 
    }; 
}]); 

Это откладывает выполнение и пусть ваш груз UI первым. $timeout возвращает обещание, поэтому остальная часть вашего кода может оставаться неизменной.

+0

Это позволит сначала загружать пользовательский интерфейс, а затем висеть. Возможно, этого достаточно для дела OP. –

+0

Да, в конце концов ему придется бежать. Единственное, что нужно сделать, это оптимизировать этот медленный метод. – DerekMT12

+0

Это сработало! Моя доска отображается и ничего не висит до того, как результаты будут вычислены и возвращены. Огромное спасибо. – Paul

2

Возможно, вы сбиваете с толку обещания нитками. Обещания не позволяют одновременное выполнение. Если вам необходимо выполнить ресурсоемкие задачи в JavaScript, сохраняя при этом пользовательский интерфейс отзывчивый, вы должны либо:

  • spawn a WebWorker (браузеры)
  • spawn a process (Node.js)
  • найти способ разделения вычислений на мелкие куски и запустить его кусок на кусок (так что интерфейс может реагировать на пользователя между каждым блоком)
+0

Спасибо! Я буду смотреть в него. Для этого случая, используя метод $ timeout, как DerekMT предложил работал для меня. – Paul

0

Я работал на встроенной системе и не было проблем с графическим интерфейсом обновления экрана на всех, но я имел вишу в то время как время от времени (его физика л устройства, так что остается включенным в течение нескольких дней/месяцев/лет), как @ DerekMT12 упоминает добавление $ таймаут фиксированной это поведение

Модуль

var myApp = angular.module('myApp',['ngRoute']); 

Сервис

var yourServiceModule = myApp.service('YourService', function ($http) { 
    this.your_method = function (a) { return a*a}; 
}); 

Контроллер

//just wrap your service,http call using $timeout 
$timeout(function() { 
    //vanilla service call 
    YourService.your_method().then(
       function (response) { 
       //console.log("sync_with_cloud: "+ response); 
       $scope.check_cloud_port_statuses_progress=100; 
       //... 
      }, 
       function(data) { 
        // Handle error here 

       $rootScope.global_config_1 += "\nError(333): cant connect to cloud at "+Date.now();+"\n\n"; 
       $scope.check_cloud_port_statuses_progress = -1; 
       } 
    ); 

}, 8);