web-dev-qa-db-ja.com

永続モデル(サーバーデータベース)が外部アプリによって変更された場合、AngularJSはビューを自動更新できますか?

私はちょうどAngularJSに精通し始めていますが、サーバー側のデータベースで何かが変更されると、ユーザーに対してリアルタイムで(更新なしで)自動更新されるビューを持つWebアプリを構築したいと思います。

AngularJSはこれを(ほとんど)自動的に処理できますか?もしそうなら、仕事で基本的なメカニズムは何ですか?

たとえば、AngularJSをセットアップして、「モデル」の変更を定期的にDBにポーリングしますか?または、何らかのCometのようなメカニズムを使用して、モデルが変更されたことをAngularJSクライアント側コードに通知しますか?

私のアプリケーションでの課題は、他の(Web以外の)サーバー側ソフトウェアがデータベースを時々更新することです。ただし、この質問は、AngularJS Webクライアントを介してデータベースを変更する複数のクライアントが存在する可能性のある純粋なWebアプリにも同様に適用されます。

82
jpeskin

いくつかの選択肢があります...

  1. $timeout$httpを使用してXミリ秒ごとにポーリングを実行できます。使用しているデータが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. 本当にハイテクになり、Angularモデルをサーバーと同期するwebsocket実装を作成できます。クライアントが何かを変更すると、その変更は自動的にサーバーに送信されます。クライアントに送信されます。
    Angularの古いバージョンで、socket.ioを使用した例を次に示します。 https://github.com/mhevery/angular-node-socketio

[〜#〜] edit [〜#〜]:#3では、これを行うために Firebase を使用しています。

96
Andrew Joslin

ノードの代わりにjettyを使用する実装を次に示します。 anglejsパーツは、angular-seedアプリに基づいています。 angularコードがイディオムであるかどうかはわかりませんが、これが機能することをテストしました。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'];

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>
15
toddg

探しているのは Firebase および Deployed です。 Firebaseにはアダプターが付属しているため、使用が簡単です。 http://angularfire.com/

3
Kenneth Lynne

だから、アンディ・ジョスリンは私の意見で最良の解決策を答えました、3番目のオプションは、websocketsまたはあなたが扱っている他の非同期ライブラリを介して双方向に状態を維持することです(これはChromeのメッセージAPI Chrome Extensions and Apps for example)、およびtoddgはそれを実現する方法の例を示しましたが、彼の例では、AngularJSでアンチパターンを実装しています。 :サービスがコントローラーを呼び出している代わりに、モデルをサービス内に配置し、コントローラーから参照する必要があります。

サービスソケットコールバックはサービスモデルを変更し、コントローラーから参照されるため、ビューを更新します。ただし、再割り当て可能なプリミティブなデータ型または変数を扱う場合は注意してください。これらを動作させるには、コントローラーを監視する必要があります。

0
bluehallu

「Discover Meteor」の本によると、Angular時計/スコープは反応性に関するMeteorの計算に似ていますが... Angularはクライアント専用であり、 -Meteorよりもきめ細かな制御。

私の印象では、Angularを使用する方が既存のアプリに反応性を追加するのに適している可能性がありますが、Meteorはすべてを使用すると急上昇します。しかし、Angular yet(私はいくつかの小さなMeteorアプリを作成しましたが)。

0
cweekly