81

我刚刚开始熟悉 AngularJS,但我想构建一个 Web 应用程序,当服务器端数据库发生变化时,它的视图会为用户实时自动更新(不刷新)。

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

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

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

4

5 回答 5

97

你有几个选择...

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

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

    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);
        };
    }
    
  3. 你可以获得真正的高科技并创建一个 websocket 实现,它将 Angular 模型与服务器同步。当客户端更改某些内容时,该更改会自动发送到服务器。或者,如果服务器发生变化,它会被发送到客户端。
    这是旧版本 Angular 中的一个示例,再次使用socket.io:https://github.com/mhevery/angular-node-socketio

编辑:对于#3,我一直在使用Firebase来执行此操作。

于 2012-06-30T21:18:32.357 回答
15

这是一个使用码头代替节点的实现。angularjs 部分基于 angular-seed 应用程序。我不确定角度代码是否是惯用的......但我已经测试过它是否有效。HTH-托德。

TimerWebSocketServlet 见

https://gist.github.com/3047812

控制器.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'];

服务.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;
            }
        };
    })});

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>
于 2012-07-04T15:24:28.347 回答
3

您正在寻找的是FirebaseDeployd。Firebase 还附带了一个适配器,使用起来轻而易举:http ://angularfire.com/

于 2013-09-17T21:15:27.913 回答
0

根据“Discover Meteor”一书,Angular 监视/范围类似于 Meteor 的反应性计算……但 Angular 是仅限客户端的,并且比 Meteor 提供的控制粒度更小。

我的印象是,使用 Angular 可能更适合为现有应用程序添加响应性,而当您将 Meteor 用于整个应用程序时,它会飙升。但是我还没有真正的 Angular 经验(尽管我已经构建了一些小型 Meteor 应用程序)。

于 2013-10-23T16:14:02.350 回答
0

因此,Andy Joslin 在他的回答中提到了我的最佳解决方案,即第三个选项,即通过 websockets 或您正在处理的任何其他异步库双向维护状态(这将是 Chrome 消息 API for Chrome Extensions 和例如应用程序),toddg 给出了一个如何实现的示例。然而,在他的示例中,他在 AngularJS 中实现了一个反模式:服务正在调用控制器。相反,模型应该放在服务内部,然后从控制器中引用。

服务套接字回调将修改服务模型,并且因为它是从控制器引用的,所以它会更新视图。如果您正在处理可以重新分配的原始数据类型或变量,请小心,这些将需要在控制器上进行监视才能使其工作。

于 2014-02-18T15:12:43.260 回答