2015-05-27 4 views
1

У меня есть функция в сервисе, которая требует много времени, чтобы вычислить, поэтому я хотел бы показать сообщение о области, чтобы показать ее вычисление. я создал (упрощенный) jsfiddle здесь: http://jsfiddle.net/rikboeykens/brwfw3g9/Угловая область не обновляется при расчете при обслуживании

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

app.service('testService', function(){ 
    this.longFunction=function(){ 
     for (var i=0; i<1000000000;i++){ 


     } 
    } 
}); 

function TestCtrl($scope, testService) 
{ 
    $scope.$apply(function(){$scope.waiting="not waiting";}); 
    $scope.longFunction = function(){ 
     $scope.waiting="waiting"; 
     testService.longFunction(); 
     $scope.waiting="not waiting"; 
    } 
} 

longFunction на TestService занимает около двух секунд, чтобы закончить, но $ scope.waiting не обновляется до «ожидания» в то время как это происходит.

Я пробовал использовать $ scope. $ Apply, но тогда я просто получаю сообщение об ошибке: $ apply уже выполняется.

Будет ли он работать, если я буду выполнять longFunction на testService асинхронно? Я изучал использование обещаний, но я не уверен, как я буду реализовывать их.

+0

Поскольку ваша длинная функция является синхронной, нет никакого способа для углового (или любого другого механизма Javascript), чтобы обновить область. Если вы хотите отображать сообщения во время дорогостоящего расчета, async действительно является способом. – doldt

+0

Каждый ответ до сих пор имеет смысл. Как добавленная стоимость, вы можете взглянуть на [этот ответ] (http://stackoverflow.com/questions/23003130/angularjs-show-loading-animation-for-slow-script-eg-while-filtering/23088231 # 23088231), чтобы поддерживать пользовательский интерфейс при выполнении долговременного обслуживания. Кроме того, вы можете посмотреть веб-работников (вероятно, гораздо лучшее решение, но у меня нет опыта в нем). –

ответ

2

Вы можете использовать $timeout.

function TestCtrl($scope, testService, $timeout) 
{ 
    $scope.waiting="not waiting"; 
    $scope.longFunction = function(){ 
     $scope.waiting="waiting"; 
     $timeout(function(){ 
      testService.longFunction(); 
      $scope.waiting="not waiting"; 
     }) 
    } 
} 
1

Это работает, но вы не видите waiting сообщение, потому что longFunction бежит синхронно, и я подозреваю, что его исполнение предотвращает UI от красили, чтобы показать waiting обновления сообщений. Когда заканчивается longFunction вызов, поток UI не занят, и это устанавливает "not waiting" сообщение мешает вам быть в состоянии прочитать "текст "waiting.

Это ожидаемое поведение в веб-браузерах, поскольку все выполняется в пользовательском интерфейсе нить, и ни один веб-браузер не может приоритизировать работу, если операции синхронны, и пользовательский интерфейс временно замораживается. Поскольку длинный цикл for или длинный расчет могут занимать много ресурсов ЦП, веб-браузерам необходимо дождаться окончания операции окрашивание экрана.

Вы можете использовать аромат setTimeout в Угловом, чтобы имитировать асинхронную операцию, и это придаст приоритет пользовательскому интерфейсу, и вы сможете увидеть m оговорка:

$scope.longFunction = function(){ 
     $scope.waiting="waiting"; 

     // Actually this is a workaround, because JS doesn't provide 
     // an elegant way of enqueueing asynchronous operations in the UI 
     // layer. BTW, does Web Workers mean something for you? ;) 
     $timeout(function() { 
      testService.longFunction(); 
     }, 0); 

     $scope.waiting="not waiting"; 
} 
1

Определенно вы должны использовать $ timeout для выполнения служебной функции. Я создал и пример на Codeopen.io: http://codepen.io/skymk/pen/EjNpKL?editors=101

app.controller('Controller', ['$scope', 'testService', '$timeout', function($scope, testService, $timeout) { 
    $scope.waiting="not waiting"; 
    $scope.longFunction = function() { 
     $scope.waiting="waiting"; 
     $timeout(function() { 
      testService.longFunction(); 
      $scope.waiting="not waiting"; 
     }, 0);  
    } 
    $scope.longFunction() 
}])