如果外部应用程序更改了持久模型(服务器数据库),AngularJS可以自动更新视图吗?

jpe*_*kin 81 javascript websocket socket.io angularjs

我刚刚开始熟悉AngularJS,但是我想构建一个Web应用程序,当服务器端数据库发生变化时,该应用程序的视图可以为用户实时自动升级(无刷新).

AngularJS可以自动处理这个(大部分)吗?如果是这样,工作的基本机制是什么?

例如,您是否以某种方式设置AngularJS以定期轮询数据库以进行"模型"更改?或者使用某种类似Comet的机制来通知AngularJS客户端代码该模型已更改?

在我的应用程序中,挑战在于其他(非Web)服务器端软件有时会更新数据库.但是这个问题同样适用于纯web应用程序,在这些应用程序中,您可能有多个客户端通过AngularJS Web客户端更改数据库,并且当其中一个客户端对DB(模型)进行更改时,每个客户端都需要更新.

And*_*lin 96

你有几个选择......

  1. 您可以使用$timeout和每隔X毫秒进行一次轮询$http,或者如果您正在使用的数据连接到REST服务,则可以使用$resource而不是$http.

  2. 您可以创建一个使用某些Websocket实现的服务,并使用它scope.$apply来处理套接字推送的更改.这是一个使用socket.io的例子,一个node.js websocket库:

    myApp.factory('Socket', function($rootScope) {
        var socket = io.connect('http://localhost:3000');
    
        //Override socket.on to $apply the changes to angular
        return {
            on: function(eventName, fn) {
                socket.on(eventName, function(data) {
                    $rootScope.$apply(function() {
                        fn(data);
                    });
                });
            },
            emit: socket.emit
        };
    })
    
    function MyCtrl($scope, Socket) {
        Socket.on('content:changed', function(data) {
            $scope.data = data;
        });
        $scope.submitContent = function() {
            socket.emit('content:changed', $scope.data);
        };
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 您可以获得真正的高科技并创建一个websocket实现,它将Angular模型与服务器同步.当客户端更改某些内容时,该更改会自动发送到服务器.或者,如果服务器发生更改,它将被发送到客户端.
    下面是在旧版本的角度,再次使用socket.io的例子:https://github.com/mhevery/angular-node-socketio

编辑:对于#3,我一直在使用Firebase来做到这一点.

  • https://github.com/mhevery/angular-node-socketio - 有一个拼写错误.固定它 (4认同)

小智 15

这是一个使用jetty而不是节点的实现.angularjs部分基于角度种子应用程序.我不确定角度代码是否是惯用的...但我已经测试过这是有效的.HTH -Todd.

TimerWebSocketServlet见

https://gist.github.com/3047812

controllers.js

// -------------------------------------------------------------
// TimerCtrl
// -------------------------------------------------------------
function TimerCtrl($scope, CurrentTime) {
    $scope.CurrentTime = CurrentTime;
    $scope.CurrentTime.setOnMessageCB(
        function (m) {
            console.log("message invoked in CurrentTimeCB: " + m);
            console.log(m);
            $scope.$apply(function(){
                $scope.currentTime = m.data;
            })
        });
}
TimerCtrl.$inject = ['$scope', 'CurrentTime'];
Run Code Online (Sandbox Code Playgroud)

services.js

angular.module('TimerService', [], function ($provide) {
    $provide.factory('CurrentTime', function () {
        var onOpenCB, onCloseCB, onMessageCB;
        var location = "ws://localhost:8888/api/timer"
        var ws = new WebSocket(location);
        ws.onopen = function () {
            if(onOpenCB !== undefined)
            {
                onOpenCB();
            }
        };
        ws.onclose = function () {
            if(onCloseCB !== undefined)
            {
                onCloseCB();
            }
        };
        ws.onmessage = function (m) {
            console.log(m);
            onMessageCB(m);
        };

        return{
            setOnOpenCB: function(cb){
               onOpenCB = cb;
            },
            setOnCloseCB: function(cb){
                onCloseCB = cb;
            },
            setOnMessageCB: function(cb){
                onMessageCB = cb;
            }
        };
    })});
Run Code Online (Sandbox Code Playgroud)

web.xml中

<servlet>
    <servlet-name>TimerServlet</servlet-name>
    <servlet-class>TimerWebSocketServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>TimerServlet</servlet-name>
    <url-pattern>/api/timer/*</url-pattern>
</servlet-mapping>
Run Code Online (Sandbox Code Playgroud)