2015-02-26 3 views
3

Я не совсем уверен, что название - лучшее описание, но мне было интересно, какой будет лучший метод, если бы у меня было какое-то событие, которое происходит за пределами цикла Angular digest, вызвать цикл дайджеста? В приложении, над которым я работаю, я использую Socket.io для передачи данных взад и вперед от других приложений в сети. В Socket.io есть некоторые события, которые могут использоваться для обновления моделей в текущей области Контроллеры. Эти изменения не отражаются в пользовательском интерфейсе до тех пор, пока не произойдет цикл дайджеста. Предполагается, что мне не нужно вызывать $ scope. $ Apply(), чтобы избежать проблем с Angular, которые уже находятся в цикле.AngularJS - Лучший способ вызвать дайджест извне Angular

Я знаю, что могу использовать $ timeout() и просто отбросить свою функцию внутри и установить тайм-аут в 0 секунд. Это то, что я сейчас использую, и он отлично работает, но мне интересно, подходит ли это лучший подход?

Пример JS

var app = angular.module('MyApp',[]); 
var socket = io.connect('http://localhost:3000'); 

app.controller('MyAppController',['$scope',function($scope) { 
    $scope.connections = 0; 
    socket.on('connect',function(sock) { 
     sock.on('event',function() { 
      $scope.connections++; 
     }; 
    }; 
}]); 

Пример HTML-

<!DOCTYPE html> 
<html lang="en" ng-app="MyApp"> 
<head></head> 
<body ng-controller="MyAppController"> 
    <p>Connections: {{connections}}</p> 
    <script src="angular.min.js"></script> 
</body> 
</html> 

Очевидно, что это очень раздели вниз, как основным, как возможный пример. Это не используемый код ACTUAL, но представляет ту же проблему. Когда событие возникает из socket.io, переменная $ scope.connections увеличивается, но пользовательский интерфейс не отражает изменения до тех пор, пока что-то еще не вызывает цикл дайджеста, $ scope. $ Apply() вызывается или я использую $ timeout().

Еще раз, у меня есть код, который работает, просто интересно, какой лучший подход к этому.

Благодаря

ответ

12

Всякий раз, когда вы знаете, что вы не в переваривать цикле, это всегда безопасно (и лучшая практика) для вызова $ сферы. $ Применить() или $ scope.digest(). Откуда вы знаете? Любой асинхронный вызов, который не выполняется через Angular API. Вот как угловой справляется с этими ситуациями внутри страны (посмотрите на код для директив ngEvent).

Использовать $ таймаут только тогда, когда вы не уверены, будет ли код, который вы используете, «внутри» угловым или нет. Это должно быть очень, очень редко. Я нужен только один раз, и я до сих пор не очень рад этому ...

var app = angular.module('MyApp',[]); 
var socket = io.connect('http://localhost:3000'); 

app.controller('MyAppController',['$scope',function($scope) { 
    $scope.connections = 0; 
    socket.on('connect',function(sock) { 
     sock.on('event',function() { 
      //wraps your code in a try catch that is handled by angular's error service. Calls $rootScope.$digest()   
      $scope.$apply(function() { 
       $scope.connections++; 
      }); 

      //OR - errors in your code will not be handled by angular 
      //also calls $rootScope.$digest() 
      $scope.connections++; 
      $scope.$apply(); 

      //OR - errors in your code will not be handled by angular 
      //Only processes watchers for $scope and it's children 
      //Fastest, but may have unintended consequences. 
      $scope.connections++; 
      $scope.$digest(); 
     }; 


    }; 
}]); 

Я предпочитаю первый вариант, потому что он получает свой код «внутри углового». Однако все трое будут работать.

Смежные вопросы