Подтвердить что ты не робот

Глобальная служба HTTP-опроса AngularJS

Я создаю веб-приложение с помощью AngularJS. Приложение должно опросить URL-адрес, который возвращает данные JSON, и сделать эти данные доступными для любой части приложения. Из того, что я прочитал до сих пор, лучше всего создать службу, которая обрабатывает опрос и хранит свой собственный внутренний кеш данных JSON, а затем внедряет сервис в любую часть приложения, которое хочет проконсультироваться с этими данными. То, что я потерял, - это как это сделать. Самый близкий пример, который я нашел, - этот вопрос, но он, похоже, создает сервис, который вручную вызывается конкретным контроллером (который сам привязан к данному маршруту), тогда как я хочу что-то, что настойчиво работает на фоне приложения навсегда независимо от того, какая часть приложения активна. Является ли это выполнимым, или я принимаю совершенно неправильный подход?

4b9b3361

Ответ 1

Здесь мое решение:

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

РЕДАКТИРОВАТЬ: Как предложил Джош Дэвид Миллер в комментариях, зависимость от этой службы должна быть добавлена ​​в блок app.run, чтобы гарантировать, что опрос сделан с момента запуска:

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

А также перенесено расписание следующего опроса после завершения предыдущего вызова. Таким образом, не было бы "укладки" вызовов в случае, если опрос зависает в течение длительного времени.

Обновлен плункер.

Ответ 2

Вот сервис angular poller в Github, который можно легко ввести в ваш контроллер.

Чтобы установить: 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);
});

Ответ 3

I forked @ValentynShybanov factory код и добавленные интервальные вызовы (каждую секунду, каждые 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
  };
});