我有一个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.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>
问题在于变化不是真正的&#34;实时&#34;。我的意思是,connected
值可能在范围内发生了变化,但是需要在页面上执行操作(按钮clic)以使视图更新具有正确的值。如果我没有在页面上执行任何操作,则不会刷新值。
我可能忘记了一些事情......但我不知道是什么......
答案 0 :(得分:2)
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()来更新任何绑定或观察者。
答案 1 :(得分:2)
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);
}
});
})
}
};
});
您可以在here中查看有关该代码段的更多信息,请转到作者Brian Ford。
修改强>
正如maurycy所说的那样,因为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);
}
});
})
}
};
});
答案 2 :(得分:-1)
因为套接字事件在AngularJS之外,所以需要消化范围:
socket.on('deviceDisconnection', function(){
$scope.connected = 'TRUE';
$scope.$digest();
});
您可以阅读this interesting article以真正理解为什么需要