AngularJS不使用socket.io刷新视图

时间:2016-03-18 15:33:16

标签: 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.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)以使视图更新具有正确的值。如果我没有在页面上执行任何操作,则不会刷新值。

我可能忘记了一些事情......但我不知道是什么......

3 个答案:

答案 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以真正理解为什么需要