如何在Angular中用$timeout包装承诺链



我有一个获取报告的服务:

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不需要保持轮询,而是需要更少的资源和更高的效率。但它需要在后端做一些工作。

对于不同的后端语言,实现会延迟。您可能需要与后端人员(或您自己)交谈。希望这能给你一些想法。

===编辑===

如果您想使用类似timeoutinterval的服务,下面的代码应该会有所帮助:

//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 });
};

很少有顾虑:

  1. 如果花费超过10秒,则应取消/解决已触发的$http请求。所以CCD_ 9是我们需要的。此处的更多信息:取消未解决的承诺
  2. 每10秒应该触发一个新的$http请求,ReportsResource.getActiveUsers()0解决了这个问题,$interval.cancel()函数将停止这个间隔
  3. 收到所需数据时,轮询应立即停止

当您在应用程序中申请时,可能需要更改代码。

相关内容

  • 没有找到相关文章

最新更新