Angular中的WebSocket服务更新范围(使用ngWebSocket)?

时间:2015-05-19 23:28:51

标签: javascript angularjs websocket

我正在尝试从websocket获取数据以自动更新控制器范围内的值。

我的服务:

mimosaApp.service("Device", function ($websocket) {
    var self = this;
    var ws = $websocket.$new({
        url: "ws://" + window.location.host + ":81",
        //mock: true,
        reconnect: true
    });
    this.data = {};

    ws.$on("$open", function() {
        ws.$emit("get", "device");
    });
    ws.$on("$message", function (message) {
        console.log("WS Received", message);
        for(var key in message) {
            self.data[key] = message[key];
        }
        console.log(self.data); // At this point, self.data contains the proper data.
    });
    this.send = function (obj) {
        ws.$emit("set", obj);
    };
});

我的简单控制器:

angular.module("MimosaApp").controller("PageController", ["Device", "$scope", "$http", function(Device, $scope, $http) {
    $scope.device = Device;
}]);

当建立套接字连接时,浏览器会发送一条消息,询问数据($ open事件)。当它获得响应时,它会使用JSON对象更新Device.data对象。

但我没有看到这反映在我的控制器范围/视图中。如果在Controller内,我设置类似Device.data.name ='blah';的东西,我可以在控制器范围/视图中看到name属性。

我对Angular有点新鲜,很抱歉,如果我的问题没有意义。 :)

我的观点是尝试使用它:

<div class="container-fluid">
    location
    <ul>
        <li ng-repeat="(key, value) in device.data">
            {{key}}: {{ value }}
        </li>
    </ul>
    <p>{{device.data.face}}</p>
</div>

2 个答案:

答案 0 :(得分:3)

查看source它似乎没有使用scope.$apply处理程序中的$on来调用摘要周期。这意味着angular不知道对其视图绑定的任何更新,因此视图中不会反映任何更改。因此,您需要在服务中手动执行此操作,您可以注入$rootScope或仅$timeout来触发摘要周期。

实施例: -

注入$timeout

 ws.$on("$message", function (message) {
        console.log("WS Received", message);
        for(var key in message) {
            self.data[key] = message[key];
        }
        console.log(self.data); // At this point, self.data contains the proper data.
       $timeout(angular.noop); //<-- just invoke a dummy digest
    });

注入$rootScope

 ws.$on("$message", function (message) {
        console.log("WS Received", message);
        for(var key in message) {
            self.data[key] = message[key];
        }
        console.log(self.data); // At this point, self.data contains the proper data.
      $rootScope.$apply(); //invoke digest
    });

甚至可以使用$q在您的服务中创建虚拟承诺。

mimosaApp.service("Device", function ($websocket, $q) {
    var self = this;
    var _dummyPromise = $q.when(); //<-- here
    var ws = $websocket.$new({
        url: "ws://" + window.location.host + ":81",
        //mock: true,
        reconnect: true
    });
    //...


    ws.$on("$message", function (message) {
        console.log("WS Received", message);
        for(var key in message) {
            self.data[key] = message[key];
        }
       _dummyPromise.then(angular.noop); //<-- here
    });
    this.send = function (obj) {
        ws.$emit("set", obj);
    };
});

答案 1 :(得分:2)

最可能的原因是$ on回调并不会触发$ digest周期来通知应用程序的其余部分任何更改。

您可以通过注入$ rootScope

手动执行此操作
mimosaApp.service("Device", function ($rootScope, $websocket)

然后在更新数据后触发$ digest

ws.$on("$message", function (message) {
    console.log("WS Received", message);
    for(var key in message) {
        self.data[key] = message[key];
    }
    if(!$rootScope.$$phase) { // prevents triggering a $digest if there's already one in progress
        $rootScope.$digest()
    }
    console.log(self.data); // At this point, self.data contains the proper data.
});