我有一个获取报告的服务:
CCD_ 1。这将使用$http
,然后返回一个promise。
然后我这样使用它:
var request = ReportsResource.getActiveUsers();
request.then(populateActiveUsersTable, handleError);
但是,问题是,在后端获取活动用户报告的请求可能需要几秒钟到30多分钟。
如果您提出请求,但没有可用的缓存报告,它会生成报告,然后请求等待该请求的数据(同样,可能是2秒或30分钟)。
如果您提出请求并且当前正在生成报告,它会立即返回一个响应,告诉您报告尚未准备好。此时,您可以继续轮询以查看报告是否已准备就绪。
如果报告已准备好(缓存),那么它会立即返回带有报告数据的响应。
我需要的是将请求封装在一个等待时间长达10秒的超时中,然后在响应完成时间超过10秒时中止,并开始轮询服务器以询问报告是否准备好。但是,如果请求在10秒内解决,它应该取消超时并正常执行承诺链。
不太确定如何处理这个。
将angular的$q与$timeout
一起使用。使用$q.defer()
创建一个deferred,创建一个超时请求,并在then处理程序中转发结果以解决您的deferred。如果请求超时,请开始轮询。立即返回延期的承诺。
var d = $q.defer() // defered for the final result
function poll() {
$http({...}).then( //poll request
function(res) {
if (ready(res))
d.resolve(res)
else {
$timeout(poll, 10000)
}
},
function(err) {
d.reject(err)
})
}
$http({ timeout: 10000, ... }).then(
function(res) {
d.resolve(res)
}, // return result directly
function(err) { // error or timeout
if (realError(err)) // check if real error
d.reject(err)
else { //timeout
$timeout(poll, 10000)
}
})
return d.promise
您可以任意重用返回的promise,经常调用then
来等待或获取缓存的结果。
在给定的情况下,我认为最好使用WebSocket而不是timeout
函数。使用WebSocket,您只需要注册每次从服务器发送更新/更改时需要运行的函数。websocket不需要保持轮询,而是需要更少的资源和更高的效率。但它需要在后端做一些工作。
对于不同的后端语言,实现会延迟。您可能需要与后端人员(或您自己)交谈。希望这能给你一些想法。
===编辑===
如果您想使用类似timeout
或interval
的服务,下面的代码应该会有所帮助:
//inside your controller
var pollingPromise = $q.defer(); //used to controll the fired $http request
var pollingActiveUsers = function() {
ReportsResource.getActiveUsers(pollingPromise).then( function(data){
//stop polling
$interval.cancel(pollingProcess);
//set to the controller's scope
$scope.activeUsers = data;
//populate the activeUsersTable
populateActiveUsersTable();
});
};
//init the first request
pollingActiveUsers();
//polling for every 10secs
var pollingProcess = $interval( function() {
//resolve the previous polling request which mean cancel the previous $http request if it waits longer than 10 secs
pollingPromise.resolve();
//start another polling, a new pollingPromise is required
pollingPromise = $q.defer();
pollingActiveUsers();
}, 10000);
//In your service ReportsResource
//you have to make another change function getActiveUsers() to make this work, you have to pass the pollingPromise to the $http method, so you can cancel the $http request:
var function getActiveUsers = function(promiseObj) {
return $http.get('someUrl', { timeout: promiseObj });
};
很少有顾虑:
- 如果花费超过10秒,则应取消/解决已触发的$http请求。所以CCD_ 9是我们需要的。此处的更多信息:取消未解决的承诺
- 每10秒应该触发一个新的$http请求,
ReportsResource.getActiveUsers()
0解决了这个问题,$interval.cancel()
函数将停止这个间隔 - 收到所需数据时,轮询应立即停止
当您在应用程序中申请时,可能需要更改代码。