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


81

AngularJSに慣れ始めたばかりですが、サーバー側のデータベースで何かが変更されたときに、ユーザーがリアルタイムで(更新なしで)自動更新されるビューを持つWebアプリを構築したいと思います。

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

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

私のアプリケーションでは、他の(Web以外の)サーバー側ソフトウェアがデータベースを更新することがあるという課題があります。ただし、この質問は、AngularJS Webクライアントを介してデータベースを変更する複数のクライアントが存在する可能性がある純粋なWebアプリにも同様に当てはまり、そのうちの1つがDB(モデル)に変更を加えるときにそれぞれを更新する必要があります。


Meteorがフレームワークでこれらすべてを実行することを発見して以来、これが私の推奨されるソリューションであることを付け加えたいと思います。将来、Angularをもう一度チェックするかもしれません。
jpeskin 2012年

Meteorはまだ「新鮮」すぎる可能性があります。遊んでみるのは良いことですが、大規模なプロダクション(安全/スケーラビリティ/パフォーマンスなど)では証明されていません。認証は1か月ほど前に追加されました。見た目は良さそうですが、待ちます。
Alex Okrushko 2012

@jpeskinこんにちは。あなたがこの質問をしたとき、私はちょうどあなたがいた場所にいます。どうしたの?(Angularを使用したい)。よろしくマーク
mark1234 2014年

回答:


97

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

  1. $timeoutとを使用してXミリ秒ごとにポーリングを実行でき$httpます。または、使用しているデータがRESTサービスに接続されている場合は、の$resource代わりにを使用できます$http

  2. Websocketの実装を使用scope.$applyし、ソケットによってプッシュされた変更を処理するために使用するサービスを作成できます。node.jsWebSocketライブラリである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

編集:#3では、Firebaseを使用してこれを行っています。


いくつかのオプションでそのような徹底的な返信をありがとう!Angularについてもっと学ぶので、これを理解するのを楽しみにしています:)
jpeskin 2012


わかりやすく、とても参考になりました。
mystrdat 2012

コントローラを破棄する必要がある場合、どのようにしてイベントハンドラのバインドを解除しますか?
RushPL 2013年

ブライアンフォードは、$ scopeのイベントシステムとクリーンアップに便乗できる優れたアプローチを採用しています。そして、それは一般的に本当にきれいになります。github.com/btford/angular-socket-io。socket.forward()を見てください
Andrew Joslin

15

これは、ノードの代わりに桟橋を使用する実装です。anglejsパーツは、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を学んでいるところですが、テンプレートなどを備えた完全なアプリがあるかどうか疑問に思っていました。
mac


0

「DiscoverMeteor」の本によると、Angularの時計/スコープは反応性に関するMeteorの計算に似ています...しかし、Angularはクライアントのみであり、Meteorよりもきめ細かい制御を提供しません。

私の印象では、Angularを使用すると、既存のアプリに反応性を追加するのに適している可能性がありますが、Meteorを使用すると、全体的に急上昇します。しかし、私はまだAngularの実際の経験がありません(いくつかの小さなMeteorアプリを作成しましたが)。


0

したがって、Andy Joslinは、私の意見の中で最良の解決策である3番目のオプションについて言及しました。これは、WebSocketまたはその他の非同期ライブラリを介して双方向に状態を維持することです(これは、Chrome拡張機能用のChromeメッセージAPIです。たとえば、アプリ)、およびtoddgは、それがどのように達成されるかの例を示しています。ただし、彼の例では、AngularJSにアンチパターンを実装しています。サービスはコントローラーを呼び出しています。代わりに、モデルをサービス内に配置してから、コントローラーから参照する必要があります。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.