AngularJS不使用socket.io刷新视图
我有一个node.js服务器应用程序,具有以下设置:AngularJS不使用socket.io刷新视图,angularjs,node.js,socket.io,Angularjs,Node.js,Socket.io,我有一个node.js服务器应用程序,具有以下设置: var express = require('express'); var io = require('socket.io'); var http = require('http'); var app = express(); app.use(express.static('public')); var server = http.createServer(app); io = io
var express = require('express');
var io = require('socket.io');
var http = require('http');
var app = express();
app.use(express.static('public'));
var server = http.createServer(app);
io = io.listen(server);
io.on('connection', function(socket){
console.log('a user is connected');
});
device.on('disconnect', function() {
console.log('we got disconnected! :( ');
io.emit('deviceDisconnection');
});
这里的设备是蓝牙连接的设备。
在客户端,我有一个AngularJS应用程序,在该应用程序的控制器中声明了以下事件订阅:
var appFront = angular.module(appFront , [])
.controller('mainController', ['$scope', '$http', function($scope,$http) {
var socket = io();
socket.on('deviceDisconnection', function(){
$scope.connected = 'TRUE';
});
}]);
当然,在视图中,我有以下绑定:
<div class="row">
<p>{{connected}}</p>
</div>
{{connected}}
问题在于,这种变化并非真正的“实时”。我的意思是,connected
值可能在范围内更改,但需要在页面上执行操作(按钮clic),以使视图更新为正确的值。如果我没有在页面上执行任何操作,则不会刷新该值
我可能忘了什么。。但是我不知道是什么..因为套接字事件在AngularJS之外,所以您需要理解范围:
socket.on('deviceDisconnection', function(){
$scope.connected = 'TRUE';
$scope.$digest();
});
您可以通过阅读来真正理解为什么需要这样做Angular没有意识到其上下文之外的更改。要解决这个问题,您应该像下面这样使用
$apply
:
var appFront = angular.module(appFront , []).controller('mainController', ['$scope', '$http', function($scope,$http) {
var socket = io();
socket.on('deviceDisconnection', function(){
$scope.$apply(function () {
$scope.connected = 'TRUE';
});
});
}]);
$scope.$apply()
将执行作为参数传递的函数,然后调用$scope.$digest()来更新任何绑定或观察程序。Socket.io事件在AngularJS外部,因此您需要警告AngularJS刚刚发生了更改:
var appFront = angular.module(appFront , [])
.controller('mainController', ['$scope', '$http', function($scope,$http) {
var socket = io();
socket.on('deviceDisconnection', function(){
$scope.$applyAsync(function () {
$scope.connected = 'TRUE';
});
});
}]);
现在这可能相当麻烦,所以您可以创建一个工厂来为您处理
app.factory('socket', function ($rootScope) {
var socket = io.connect();
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$apply(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$apply(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
您可以在中查看有关该代码段的更多信息,请访问作者Brian Ford
编辑
如前所述,由于Angular 1.3更好地使用$applyAsync,而且由于上面的代码段是在2012年编写的,所以有点过时,所以更好的版本应该是这样的
app.factory('socket', function ($rootScope) {
var socket = io.connect();
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
$rootScope.$applyAsync(function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
$rootScope.$applyAsync(function () {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
不要在代码中放入
$scope.$digest()
,如果应用程序增长并且$digest将更频繁地被触发,它将在progres中抛出JS错误$digest
使用$scope.$apply
或在angularjs的更新版本中$scope.$applyAsync
这就是为什么Angular1.3用户在不指定时间的情况下使用$timeout
对其进行微调,从angular 1.3开始,有一个专门为此设计的ApplySync
。我不知道applyAsync。从angular 1.3开始使用$scope.$applyAsync
哪一个更好呢?我的错,错过了。好东西:)坦白地说,这是最好的解决方案,将socket.io包装为angular service使其变得很好easier@maurycy为作者添加了更多可见的学分,并添加了一个建议使用$applyAsync