使用 socketio 服务,我想将新数据传递给指令。 传递实际数据已经有效,并且我在指令中收到新值。为此,我从指令中调用 socketio 服务,并将回调作为参数传递给服务。
目标
通过socket.io服务接收设备信息(设备名称、设备状态)并更新相应设备指令的相应范围($scope.value.device_state
)。
问题
该指令有多个实例。每次实例化该指令时,都会将一个新的回调函数发送到 socketio 服务并进行注册。这样,如果 socketio 服务收到新数据,就会执行多个回调。
问题示例
该指令被实例化 7 次。如果 socket.io 服务收到新数据,似乎 7 个指令中的每一个都会收到新数据可用的通知 7 次。
Controller
Controller 加载包含多个设备信息的初始 JSON。设备通过名称 (device_name) 引用。
[{"device_name":"device1","device_state":"ON"},{"device_name":"device2","device_state":"OFF"}]
查看
该 View 显示每个设备的设备状态。
<div>{{value.device_state}}</div>
Socket.io 服务
socket.io 服务接收新的设备状态并运行回调。
app.service('service_websocket', function () {
var api = {};
var socket = io.connect();
api.getDeviceState = function(callback) {
socket.on('send:device_state', callback);
};
return api;
});
已收到 Socket.io 服务数据
这就是新数据的样子。这意味着“device2”应设置为“ON”。
{"device_name":"device2","device_state":"ON"}
指令
该指令将回调传递给socket.io 服务。每个指令的回调都是相同的。一旦收到新数据,它就应该更新相应设备的 device_state(由 device_name 引用)。
.directive('device', function(){
return {
restrict: 'E',
scope: {
value: '='
},
templateUrl: 'templates/partial_device.tpl.html',
controller: ['$scope', 'service_device', 'service_websocket',function($scope, service_device, service_websocket) {
service_websocket.getDeviceState(function(data) {
if($scope.value.device_name == data.device_name) {
$scope.value.device_state = data.device_state;
}
});
}]
};
});
问题
您将如何实现这一点? 非常感谢任何帮助。
最佳答案
Issue
There are multiple instances of the directive. Everytime the directive is instanciated, a new callback function is sent to the socketio service and gets registered. This way multiple callbacks are executed if new data is received by the socketio service.
好吧,您的事件 send:device_state
没有封装任何有意义的“状态”。
如果您的页面中有多个设备(指令)注册到该事件,那么所有这些设备(指令)显然都会被触发。
1) 您可以考虑重构服务器端代码并发送例如针对特定设备的自定义事件,例如 send:device_state_device2
(您已在 json 中包含此信息)
2)或者您可以处理此客户端,保留回调映射并决定触发哪一个
var cb = {}; //map of callback
function wrapperFn(){
return function(data){
//trigger the callback only of the target device if exists
cb[data.device_name] && cb[data.device_name]();
}
}
api.getDeviceState = function(deviceName, callback) {
cb[deviceName] = callback || function(){};
socket.on('send:device_state', wrapperFn());
};
另一件事需要注意的是,您传递给服务的回调是在 Angular 环境之外执行的,为了反射(reflect)对模板的更改,您应该手动触发将代码包装在 $apply 中的 dygest 周期
service_websocket.getDeviceState(function(data) {
$scope.$apply(function(){
if($scope.value.device_name == data.device_name) {
$scope.value.device_state = data.device_state;
}
});
});
关于javascript - AngularJS:如何将socket.io服务数据传递给相应的指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44050500/