Javascript AngularJS 全局 http 轮询服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14944936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS global http polling service
提问by sslepian
I'm building a web app using AngularJS. The app needs to poll a URL that returns JSON data and make that data available to any part of the app. From what I've read so far, my best bet is to create a service that handles the polling and keeps its own internal cache of the JSON data, and then inject the service into any part of the app that wants to consult that data. What I'm lost on is how to actually go about doing that. The closest example I've found is this question, but it appears to be creating a service that's manually called by a specific controller (which is itself tied to a given route), whereas I want something that persistently runs in the background of the app forever regardless of what part of the app is active. Is this doable, or am I taking the completely wrong approach?
我正在使用 AngularJS 构建一个 Web 应用程序。应用程序需要轮询返回 JSON 数据的 URL,并使该数据可用于应用程序的任何部分。从我目前所读到的内容来看,我最好的办法是创建一个服务来处理轮询并保留自己的 JSON 数据内部缓存,然后将该服务注入到应用程序中想要查询该数据的任何部分。我迷失的是如何真正做到这一点。我发现的最接近的例子是这个问题,但它似乎正在创建一个由特定控制器手动调用的服务(它本身与给定的路由绑定),而我想要一些在应用程序后台持续运行的东西永远不管应用程序的哪个部分处于活动状态。这是可行的,还是我采取了完全错误的方法?
回答by Valentyn Shybanov
Here my solution:
这是我的解决方案:
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
};
});
(calls just to show that polling is been done)
(打电话只是为了表明投票已经完成)
http://plnkr.co/edit/iMmhXTYweN4IrRrrpvMq?p=preview
http://plnkr.co/edit/iMmhXTYweN4IrRrrpvMq?p=preview
EDIT:As Josh David Miller suggested in comments, dependency on this service should be added in app.run block to ensure polling is done from start:
编辑:正如 Josh David Miller 在评论中所建议的,应该在 app.run 块中添加对此服务的依赖,以确保从一开始就完成轮询:
app.run(function(Poller) {});
And also moved scheduling of next poll after previous call finished. So there would not be "stacking" of calls in case if polling hangs for a long time.
并且在上一次调用完成后移动了下一次轮询的调度。因此,如果轮询长时间挂起,就不会“堆叠”调用。
Updated plunker.
更新的plunker。
回答by Emma Guo
Here is an angular poller serviceon Github that can be easily injected into your controller.
这是Github 上的一个angular poller 服务,可以轻松注入到您的控制器中。
To install:
bower install angular-poller.
安装:
bower install angular-poller。
Since you want to start a global polling service that runs in the background forever, you can do:
既然你想启动一个永远在后台运行的全局轮询服务,你可以这样做:
// 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);
});
Now it will run in the background forever until you call myPoller.stop()or poller.stopAll().
现在它将永远在后台运行,直到您调用myPoller.stop()或poller.stopAll()。
If you want to use the callback data of this poller in other controllers, you can simply do:
如果要在其他控制器中使用此轮询器的回调数据,只需执行以下操作:
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);
});
回答by lito
I forked @ValentynShybanov's factory code and added intervals calls (every second, every 5 secs, etc), also you can stop and start the poller as you wish:
我分叉了@ValentynShybanov 的工厂代码并添加了间隔调用(每秒、每 5 秒等),您也可以根据需要停止和启动轮询器:
http://plnkr.co/edit/EfsttAc4BtWSUiAU2lWf?p=preview
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
};
});

