AngularJS不会使用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.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
值可能在范围中改变,但是需要在页面上执行一个操作(buttonclic),使视图以正确的值更新。 如果我没有在页面上做任何事情,价值不刷新。
我可能忘了一些东西..但我不知道是什么..
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'; }); }); }]);
现在这可能非常麻烦,所以你可以创build一个工厂来为你处理
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。
编辑
正如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); } }); }) } }; });
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()
将执行一个作为parameter passing的函数,然后调用$ scope。$ digest()来更新绑定或监视器。
由于套接字事件在AngularJS之外,因此需要消化范围:
socket.on('deviceDisconnection', function(){ $scope.connected = 'TRUE'; $scope.$digest(); });
你可以阅读这个有趣的文章 ,真正理解为什么这是必要的
- Expressjs路线与Angular路线问题直接加载url
- 允许与Yeoman(1.0)grunt服务器进行跨域调用
- 如何使用量angular器在canvas上的特定位置执行单击事件
- 即使JSON数据在MongoDB上持久化,nodeJS方法也会报错
- Multivision的应用 – 寻找熟悉Joe Eames Course的MeanStack的人
- 在OS X上的Angular 2教程El Capitan在浏览器中返回“Can not GET /”
- angularNgRoute“/”的作品,但其余的不?
- 如何在你的Ionic / AngularJs应用程序中包含和使用节点模块?
- jQuery与AngularJS与Node.js的区别