Я создаю веб-приложение с помощью AngularJS. Приложение должно опросить URL-адрес, который возвращает данные JSON, и сделать эти данные доступными для любой части приложения. Из того, что я прочитал до сих пор, лучше всего создать службу, которая обрабатывает опрос и хранит свой собственный внутренний кеш данных JSON, а затем внедряет сервис в любую часть приложения, которое хочет проконсультироваться с этими данными. То, что я потерял, - это как это сделать. Самый близкий пример, который я нашел, - этот вопрос, но он, похоже, создает сервис, который вручную вызывается конкретным контроллером (который сам привязан к данному маршруту), тогда как я хочу что-то, что настойчиво работает на фоне приложения навсегда независимо от того, какая часть приложения активна. Является ли это выполнимым, или я принимаю совершенно неправильный подход?
Глобальная служба HTTP-опроса AngularJS
Ответ 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
};
});