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


81

我刚刚开始熟悉AngularJS,但我想构建一个Web视图,该视图具有一个视图,当服务器端数据库中发生某些更改时,该视图将为用户实时自动更新(不刷新)。

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

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

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


我想补充一点,因为我发现Meteor在框架中为您完成了所有这一切,所以这是我目前的首选解决方案。将来可能再次检查Angular。
jpeskin 2012年

流星可能仍然太“新鲜”-很好玩,但尚未在大规模生产(安全/可伸缩性/性能/等)中证明自己。身份验证是在一个月前添加的。看起来不错,但会等待。
Alex Okrushko

@jpeskin嗨。当您问这个问题时,我正好位于您所在的位置。你最终做了什么?(我想使用Angular)。关于Mark
mark1234

Answers:


97

您有几种选择...

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

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


感谢您提供多种选择的详尽答复!当我进一步了解Angular时,希望能理解这一点:)
jpeskin 2012年


谢谢您的简单理解答复,非常有帮助。
mystrdat 2012年

如果控制器需要销毁,您将如何解除对事件处理程序的绑定?
RushPL

布赖恩·福特(Brian Ford)有一个很棒的方法,可让您搭载$ scope的事件系统和清理。并使其总体上真正干净。github.com/btford/angular-socket-io。看看socket.forward()
安德鲁·乔斯林

15

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

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'];

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;
            }
        };
    })});

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>

这是一个极好的例子。我只是在学习Angular.js,想知道您是否有完整的带有模板等的应用程序可以学习?
2012年


0

根据“发现流星”一书,Angular的手表/范围类似于Meteor关于反应性的计算...但是Angular仅限客户端使用,并且比Meteor提供更少的粒度控制。

我的印象是,使用Angular可能更适合向现有应用程序添加反应性,而当您将Meteor用于整个应用程序时,它会飞速发展。但是我还没有使用Angular的实际经验(尽管我已经构建了一些小型Meteor应用程序)。


0

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

服务套接字回调将修改服务模型,并且由于它是从控制器引用的,因此它将更新视图。但是,如果要处理可重新分配的原始数据类型或变量,则需要在控制器上进行监视以使其正常工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.