34

我正在使用 AngularJS 构建一个网络应用程序。应用程序需要轮询返回 JSON 数据的 URL,并使该数据可用于应用程序的任何部分。根据我目前所读到的内容,我最好的选择是创建一个服务来处理轮询并保留其自己的 JSON 数据内部缓存,然后将该服务注入到应用程序中想要查询该数据的任何部分。我迷失的是如何真正做到这一点。我发现的最接近的例子是这个问题,但它似乎正在创建一个由特定控制器手动调用的服务(它本身与给定的路由绑定),而我想要在应用程序的后台持续运行的东西永远不管应用程序的哪个部分处于活动状态。这是可行的,还是我采取了完全错误的方法?

4

3 回答 3

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

编辑:正如 Josh David Miller 在评论中建议的那样,应该在 app.run 块中添加对该服务的依赖,以确保从一开始就完成轮询:

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

并且在上一次通话完成后还移动了下一次轮询的安排。因此,如果轮询挂起很长时间,就不会有调用的“堆叠”。

更新了 plunker。

于 2013-02-18T21:08:00.127 回答
21

这是 Github 上的一个angular poller 服务,可以很容易地注入到你的控制器中。

要安装: bower install angular-poller.

既然你想启动一个永远在后台运行的全局轮询​​服务,你可以这样做:

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

现在它将永远在后台运行,直到您调用myPoller.stop()poller.stopAll()

如果您想在其他控制器中使用此轮询器的回调数据,您可以简单地执行以下操作:

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);
});
于 2014-01-03T22:47:01.243 回答
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
  };
});
于 2016-03-19T13:31:15.133 回答