Angular 中的 WebSocket 服务更新范围(使用 ngWebSocket)?
WebSocket Service update Scope in Angular (Using ngWebSocket)?
我正在尝试从 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 对象。
但我没有在我的控制器中看到这一点 scope/view。如果在控制器内部,我设置类似 Device.data.name ='blah';
我可以在控制器 scope/view 中看到名称 属性。
我对 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>
查看 source 它似乎没有在 $on
处理程序中使用 scope.$apply
调用摘要循环。这意味着 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);
};
});
最可能的原因是 $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.
});
我正在尝试从 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 对象。
但我没有在我的控制器中看到这一点 scope/view。如果在控制器内部,我设置类似 Device.data.name ='blah';
我可以在控制器 scope/view 中看到名称 属性。
我对 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>
查看 source 它似乎没有在 $on
处理程序中使用 scope.$apply
调用摘要循环。这意味着 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);
};
});
最可能的原因是 $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.
});