AngularJs /有效地将WebSockets事件/消息传播到各种控制器

时间:2014-04-30 23:39:02

标签: javascript angularjs callback websocket

使用AngularJs,我编写了一个旨在处理WebSocket连接的factory 这是其代码:

.factory('WebSocketConnection', function () {
        var service = {};
        service.callbacks = [];
        service.connect = function() {
            if(service.ws) 
              return;
            var ws = new WebSocket("ws://localhost:9000/ws");
            ws.onmessage = function (message) {
                angular.forEach(service.callbacks, function(callback){
                    callback(message);
                });
            };
            service.ws = ws;
        };

        service.send = function(message) {
            service.ws.send(message);
        };

        service.subscribe = function(callback) {
          service.callbacks.push(callback);
        };
        return service;
});

基本上,它允许每个Angular组件(如controllerfactory / service)注册特定的回调,以便处理消息;因此回调数组 这是一个有趣的听力摘录controller

WebSocketConnection.subscribe(function (message) {  
      $scope.$apply(function () {
         var data = angular.fromJson(message.data);
         $scope.notifications.push(data);
      });
});

因此回调数组将包含此函数。

但是......如果我在某个时间不再需要这个控制器怎么办? (例如,当我导航到基于另一个控制器的其他页面时)
每次离开控制器的使用时,我都会被迫从数组中删除回调项(此函数),以避免在处理任何其他消息时无效,可能是冲突的回调过程。
不方便......

我想到了一种从工厂$rootScope广播事件的方法,这样一个特定的控制器就不必自己管理他的听众/订阅。
但我并不想涉及所有范围树,包括所有与之无关的范围。

什么是好习惯?

注意:我需要实现一个关系1-N,其中1是WebSocket处理程序(工厂)和N,任何并行的活动Angular组件,每个组件都需要监听消息。

2 个答案:

答案 0 :(得分:1)

我建议在服务或工厂对象中维护您的模型。这将使您能够与存在的数据进行交互,并且在收到消息时不依赖于应用程序的状态(存在哪些控制器)。它还可以允许您强制执行以下概念:

  

$ scope 模型而不是$ scope 模型

这可能看起来像这样:

ws.onmessage = function(event) {
    $rootScope.$apply(function(){
        Service.notifications.push(event.data);
    }
}

angular.module('MyApp').controller('MyCtrl', ['$scope', 'Service', 
function($scope, Service) {
    $scope.notifications = Service.notifications; //references are ===
}])

为了实现灵活性,您可以使用消息中包含的数据来确定需要更新的注射/方法,然后使用$injector

答案 1 :(得分:1)

感谢@calebboyd提醒我$scope的{​​{1}}事件的存在,我想我找到了一个很好的方法来实现我的要求。

让控制器取消订阅的半自动方式是添加这段代码:

destroy

订阅机制如下所示:

$scope.$on("$destroy",function() {
  WebSocketConnection.unsubscribe($scope.$id);      
});

因此,完整的工厂代码将是:

WebSocketConnection.subscribe($scope.$id, function (message) {   //note the $scope.$id parameter
      $scope.$apply(function () {
         var data = angular.fromJson(message.data);
         $scope.notifications.push(data);
      });
});

这就是诀窍:然后可以检测并删除充当侦听器的每个无用回调。