使用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组件(如controller
或factory
/ 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组件,每个组件都需要监听消息。
答案 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);
});
});
这就是诀窍:然后可以检测并删除充当侦听器的每个无用回调。