2013-02-18 4 views
30

私はAngularJSを使用してWebアプリケーションを構築しています。アプリはJSONデータを返すURLをポーリングし、そのデータをアプリのどの部分でも利用できるようにする必要があります。私が今までに読んだところでは、ポーリングを処理し、独自のJSONデータの内部キャッシュを保持するサービスを作成し、そのデータを参照したいアプリケーションの任意の部分にサービスを注入することをお勧めします。私が迷っているのは、実際にそれをやり遂げる方法です。私が見つけた最も近い例はthis questionですが、特定のコントローラ(それは特定のルートに結びついています)によって手動で呼び出されるサービスを作成しているように見えますが、私は永久にアプリケーションのバックグラウンドで永久に実行するものアプリのどの部分がアクティブであるかにかかわらずこれは実行可能か、まったく間違ったアプローチですか?ここでAngularJSグローバルhttpポーリングサービス

答えて

41

私の解決策:

app.factory('Poller', function($http, $timeout) { 
    var data = { response: {}, calls: 0 }; 
    var poller = function() { 
    $http.get('data.json').then(function(r) { 
     data.response = r.data; 
     data.calls++; 
     $timeout(poller, 1000); 
    });  
    }; 
    poller(); 

    return { 
    data: data 
    }; 
}); 

が(ちょうどそのポーリングが行われている表示するために呼び出します)

http://plnkr.co/edit/iMmhXTYweN4IrRrrpvMq?p=preview

はEDIT:ジョシュデヴィッド・ミラーが、この上の依存関係、コメントで示唆したようにapp.runブロックにサービスを追加して、開始からポーリングが確実に行われるようにしてください。

app.run(function(Poller) {}); 

また、前回のコール終了後に次のポーリングのスケジューリングを移動しました。したがって、ポーリングが長時間ハングした場合のために、コールの「スタッキング」はありません。

プラカードが更新されました。

+2

+1をしかし、彼は何かが常に動作して欲しい、そうも 'app.run' BLOから、それをトリガーckを実行して、最初から実行されていることを確認します。私は 'poller'関数をチェックして' $ http'への前回の呼び出しを完了させ、無限にスタックするのではなく、AngularJSの約束の実装でそれを行う方法はないようです。 –

+1

Thnx。両方の項目を回答に追加しました。また、スタッキングについては、次のポーリングのスケジューリングを前のコールの「次へ」に移動するだけで回避できます。ではない? –

+1

恐ろしい! :-)私は、 '$ q'が実装していない、isFulfilled()の元の' q'の約束事に集中していたと思います。笑 –

20

コントローラに簡単に注入できるGithubのangular poller serviceがあります。

インストールする: bower install angular-poller

あなたは永遠にバックグラウンドで実行され世界的なポーリングサービスを開始したいので、あなたが行うことができます:あなたはmyPoller.stop()poller.stopAll()を呼び出すまで

// Inject angular poller service. 
var myModule = angular.module('myApp', ['poller']); 

// The home/init controller when you start the app. 
myModule.controller('myController', function($scope, $resource, poller) { 

    // Define your resource object. 
    var myResource = $resource(url[, paramDefaults]); 

    // Create and start poller. 
    var myPoller = poller.get(myResource); 

    // Update view. Most likely you only need to define notifyCallback. 
    myPoller.promise.then(successCallback, errorCallback, notifyCallback); 
}); 

今では永遠に、バックグラウンドで実行されます。

あなたが他のコントローラにこのポーラーのコールバックデータを使用したい場合、あなたは、単に行うことができます。

myModule.controller('anotherController', function($scope, $resource, poller) { 

    /* 
    * You can also move this to a $resource factory and inject it 
    * into the controller so you do not have to define it twice. 
    */ 
    var sameResource = $resource(url[, paramDefaults]); 

    /* 
    * This will not create a new poller for the same resource 
    * since it already exists, but will simply restarts it. 
    */ 
    var samePoller = poller.get(sameResource); 

    samePoller.promise.then(successCallback, errorCallback, notifyCallback); 
}); 
+0

これは素晴らしいライブラリのようです。そこに何かサンプルアプリがありますか? – ardochhigh

+0

@ardochhighすぐにサンプルアプリケーションを追加する予定です。しかしそれが起こる前に、[readme](https://github.com/emmaguo/angular-poller/blob/master/README.md)ページをチェックアウトすることができます。 :-) –

+0

ありがとう@江南郭READMEのページはかなり詳細です。私はAngularをかなり新しくしており、まだいくつかのコンセプトに苦しんでいます。あなたのライブラリは私の必要条件に完璧に見えます。おそらく、私は概念の証明のためにプランナーを作ろうとします。知らせます。 – ardochhigh

0

私はValentynShybanovの工場コード@フォークと間隔コール(毎秒ごとに5秒、などを追加しました)、また、あなたが停止し、ポーラーを開始し、あなたが望むようにすることができます

http://plnkr.co/edit/EfsttAc4BtWSUiAU2lWf?p=preview

app.factory('Poller', function($http, $timeout) { 
    var pollerData = { 
    response: {}, 
    calls: 0, 
    stop: false 
    }; 

    var isChannelLive = function() { 
    $http.get('data.json').then(function(r) { 
     if (pollerData.calls > 30 && pollerData.stop === false) { // call every minute after the first ~30 secs 
     var d = new Date(); 
     console.log('> 30: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 10000); 
     } else if (pollerData.calls > 15 && pollerData.calls <= 30 && pollerData.stop === false) { // after the first ~15 secs, then call every 5 secs 
     var d = new Date(); 
     console.log('> 15 & <= 30: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 5000); 
     } else if (pollerData.calls <= 15 && pollerData.stop === false) { // call every 1 second during the first ~15 seconds 
     var d = new Date(); 
     console.log('<= 15: ' + d.toLocaleString() + ' - count: ' + pollerData.calls); 
     pollerData.calls++; 
     $timeout(isChannelLive, 1000); 
     } 

     pollerData.response = r.data; 
    }); 

    }; 
    var init = function() { 
    if (pollerData.calls === 0) { 
     pollerData.stop = false; 
     isChannelLive(); 
    } 
    }; 
    var stop = function() { 
    pollerData.calls = 0; 
    pollerData.stop = true; 
    }; 

    return { 
    pollerData: pollerData, // this should be private 
    init: init, 
    stop: stop 
    }; 
});