我正在使用AngularJS构建一个Web应用程序。该应用程序需要轮询一个返回JSON数据的URL,并将该数据提供给应用程序的任何部分。从我到目前为止所读到的内容来看,我最好的办法是创建一个处理轮询并保留其自己的JSON数据内部缓存的服务,然后将服务注入到想要查询该数据的应用程序的任何部分。我迷失的是如何实际去做。我发现的最接近的例子是this question,但它似乎是创建一个由特定控制器(它本身与给定路由绑定)手动调用的服务,而我想要在后台持续运行的东西无论应用程序的哪个部分处于活动状态,应用程序永远都是。这是可行的,还是我采取了完全错误的做法?
答案 0 :(得分:42)
这是我的解决方案:
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。
答案 1 :(得分:21)
这是Github上的angular poller service,可以很容易地注入你的控制器。
安装:
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);
});
答案 2 :(得分: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
};
});