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

Javascript 如果外部应用程序更改了持久模型(服务器数据库),AngularJS能否自动更新视图?,javascript,angularjs,websocket,socket.io,Javascript,Angularjs,Websocket,Socket.io,我刚刚开始熟悉AngularJS,但我想构建一个web应用程序,当服务器端数据库发生变化时,该应用程序的视图会自动实时更新(无需刷新) AngularJS能(大部分)自动为我处理这个问题吗?如果是这样,工作的基本机制是什么 例如,您是否以某种方式设置AngularJS定期轮询DB以获取“模型”更改?或者使用某种类似Comet的机制通知AngularJS客户端代码模型已更改 在我的应用程序中,挑战在于其他(非web)服务器端软件有时会更新数据库。但这个问题同样适用于纯web应用程序,在纯web应用

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

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

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


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

您有一些选择

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

  • 您可以创建一个服务,该服务使用一些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);
        };
    }
    
  • 您可以使用非常高的技术,创建一个websocket实现,将角度模型与服务器同步。当客户端更改某些内容时,该更改会自动发送到服务器。或者,如果服务器发生更改,则会将其发送到客户端。
    下面是Angular旧版本中的一个示例,再次使用socket.io:


  • 编辑:对于#3,我一直在使用它来完成此操作。

    这里有一个使用jetty而不是node的实现。angularjs部分基于AngularSeed应用程序。我不确定angular代码是否是惯用的…但我已经测试过它是否有效。托德

    TimerWebSocketServlet请参阅

    controllers.js services.js web.xml
    
    TimerServlet
    TimerWebSocketServlet
    0
    TimerServlet
    /api/定时器/*
    
    您要找的是和。 Firebase还配备了一个适配器,使使用它变得轻而易举:

    根据《发现流星》一书,角度手表/示波器与流星关于反应性的计算类似。。。但Angular仅限于客户端,其粒度控制不如Meteor


    我的印象是,使用Angular可能更适合为现有应用程序添加反应性,而Meteor在整个应用程序中使用时会飙升。但是我还没有使用Angular的实际经验(尽管我已经构建了一些小型Meteor应用程序)。

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


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

    感谢您的全面回复,并提供了几个选项ns!期待着在我了解更多关于Angular的知识时理解这一点:)-有一个speling错误。修正了它谢谢你一个简单易懂的回复,非常有用。如果需要销毁控制器,你将如何继续解除事件处理程序的绑定?Brian ford有一个很好的方法,可以让你借助$scope的事件系统和清理。使它总体上非常干净。看看socket.forward()这是一个很好的例子。我只是在学习Angular.js,想知道你是否有完整的应用程序和模板等,以学习?我想补充一点,我已经发现Meteor在框架中为你做了所有这些,所以这是我现在首选的解决方案。将来可能会再次查看Angular。Meteor可能仍然太“新鲜”-它很适合玩,但尚未在大型生产中证明自己(安全性/可伸缩性/性能/等等)。身份验证是在一个多月前添加的。看起来不错,但会等的。@jpeskin-Hi。当你问这个问题的时候,我就在你的身边。你最后做了什么?(我想使用角度)。关于MarkCheck。
    // -------------------------------------------------------------
    // 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'];
    
    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;
                }
            };
        })});
    
    <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>