javascript - AngularJS:如何将socket.io服务数据传递给相应的指令

标签 javascript angularjs socket.io

使用 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/

相关文章:

javascript - 在 D3.js 树的中心和不同节点之间绘制不同颜色的 "strokes"

node.js - NodeJS - 访问套接字内的 session

import - Angular2 CLI Socket.io(第 3 方库导入)

javascript - 如何在 Angular js中制作滑动切换功能

angularjs - 如果空白,带有 md-chips 的 Angular Material md-autocomplete 不会清除搜索

javascript - WebRTC远程视频黑屏

javascript - 如何使用 jQuery 获取该元素的索引?

javascript - 检查点击了什么然后条件,如果没有然后条件

javascript - 如何在angularjs中访问$localStorage中保存的数据

javascript - 如何检查取消按钮上的 AngularJs 表单字段?