Angularjs 如何在切换路由时取消资源承诺 [英] Angularjs how to cancel resource promise when switching routes

查看:20
本文介绍了Angularjs 如何在切换路由时取消资源承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始接触 Angularjs.我有一个问题,我认为这与承诺有关.

I'm just getting my feet wet with Angularjs. I have an issue which I think has something to do with promises.

假设我加载路由A",它通过它的控制器发出几个 ajax 请求:

Let's say I load route 'A' which makes several ajax requests through it's controller:

allSites = AllSites.query({ id:categoryID });

allSites.$promise.then(function(allSites){
    //add stuff to the scope and does other things 
    //(including making another ajax request)
});

然后我有路由B",它通过控制器发出自己的 API 请求:

Then I have route 'B' which makes it's own API request through it's controller:

$scope.categories = Category.query();

这是路线A"当前使用的工厂服务:

Here's the factory service currently used by route 'A':

.factory('AllSites',function($resource){
    return $resource('api/categorySites/:id');
});

当我第一次查看路线A"但在A"完成加载之前切换到B"时,路线B"坐下来等待A"中最初请求的所有内容完成(实际上,查询()请求已发出,但它不会解决,直到来自 'A' 的那个请求完成,此时 .then() 中的内容继续发生,即使我不需要它作为我现在在另一条路线上.

When I first view route 'A' but then switch to 'B' before 'A' is finished loading, route 'B' sits and waits for everything initially requested in 'A' to finish (actually, the query() request is made, but it won't resolve until the one from 'A' does, at that point, the stuff inside .then() continues to happen, even though I don't need it as I'm now on another route.

正如您在我的 devtools 时间线中看到的,绿线表示我何时切换到路线B".直到上述两个请求(通常非常快的请求)完成后,路由B"的请求才得到解决.(此时我可以作为用户使用该视图).然后,在那之后,更多的承诺从路径A"解析.

As you can see in my devtools timeline, the green line indicates when I switched to route 'B'. The request for route 'B' didn't resolve until the two requests above did (a request that is usually very fast). (at which point I'm able to use the view as a user). Then, after that, more promises resolve from route 'A'.

我到处寻找答案,但只能找到想要推迟"路由加载直到承诺得到解决的人.但就我而言,我几乎想要相反的.我想在切换时终止这些请求.

I've searched everywhere for an answer and can only find people that want to "defer" the route loading until promises are resolved. But in my case I almost want the opposite. I want to kill those requests when I switch.

有人提出了同样的未回答问题:拒绝 Angularjs 资源承诺

Here's someone else with the same, unanswered question: Reject Angularjs resource promises

感谢任何帮助.

推荐答案

首先,我决定我需要使用 $http 因为我找不到任何使用 $ 的解决方案资源,我也不能让它自己工作.

First of all, I decided I needed to use $http since I couldn't find any solution that used $resource, nor could I get it to work on my own.

因此,根据@Sid 的回答,使用 http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm

So here's what my factory turned into, based on @Sid's answer here, using the guide at http://www.bennadel.com/blog/2616-aborting-ajax-requests-using-http-and-angularjs.htm

.factory('AllSites',function($http,$q){

    function getSites(categoryID) {

        // The timeout property of the http request takes a deferred value
        // that will abort the underying AJAX request if / when the deferred
        // value is resolved.
        var deferredAbort  = $q.defer();

        // Initiate the AJAX request.
        var request = $http({
            method: 'get',
            url: 'api/categorySites/'+categoryID,
            timeout: deferredAbort.promise
        });

        // Rather than returning the http-promise object, we want to pipe it
        // through another promise so that we can "unwrap" the response
        // without letting the http-transport mechansim leak out of the
        // service layer.
        var promise = request.then(
            function( response ) {
                return( response.data );
            },
            function() {
                return( $q.reject( 'Something went wrong' ) );
            }
        );

        // Now that we have the promise that we're going to return to the
        // calling context, let's augment it with the abort method. Since
        // the $http service uses a deferred value for the timeout, then
        // all we have to do here is resolve the value and AngularJS will
        // abort the underlying AJAX request.
        promise.abort = function() {
            deferredAbort.resolve();
        };

        // Since we're creating functions and passing them out of scope,
        // we're creating object references that may be hard to garbage
        // collect. As such, we can perform some clean-up once we know
        // that the requests has finished.
        promise.finally(
            function() {
                promise.abort = angular.noop;
                deferredAbort = request = promise = null;
            }
        );

        return( promise );
    }

    // Return the public API.
    return({
        getSites: getSites
    });

});

然后,在我的控制器中(我的问题中的路由A"):

Then, in my controller (route 'A' from my problem):

var allSitesPromise = AllSites.getSites(categoryID);

$scope.$on('$destroy',function(){
    allSitesPromise.abort();
});

allSitesPromise.then(function(allSites){
    // do stuff here with the result
}

我希望工厂不要那么乱,但我会拿走我能得到的.但是,现在有一个单独的相关问题这里,虽然承诺被取消,接下来的行动仍然被推迟.如果您对此有答案,可以在此处发布.

I wish the factory wasn't so messy, but I'll take what I can get. However, now there's a separate, related issue Here where, though the promise was cancelled, the next actions are still delayed. If you have an answer for that, you can post it there.

这篇关于Angularjs 如何在切换路由时取消资源承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆