2016-12-28 76 views
0

在我的Angular应用程序中,用户可以返回到前一个屏幕(这只是隐藏当前屏幕)。用户可能会在长时间运行的AJAX请求中执行此操作。如果发生这种情况,我想在幕后取消Ajax请求。

我可以得到ngresource的$ cancelRequest工作,但它会导致错误回调被抛出。有没有办法让这种情况不发生,或将$ cancelRequest与服务器的失败通信区分开来?提前致谢。

普拉克(有一些额外的UI吧):http://plnkr.co/edit/tYj4FRQ9EaCTH4iW9PcL?p=preview

var app = angular.module("app", ["ngResource"]); 

app.service("Photos", function($resource) { 
    return $resource(null, {}, { 
    getPhotos: { 
     url: "http://jsonplaceholder.typicode.com/photos", 
     method: "GET", 
     isArray: true, 
     cancellable: true 
    } 
    }); 
}); 

MyController.$inject = ["$log", "$timeout", "Photos"]; 

function MyController($log, $timeout, Photos) { 
    var vm = this; 
    vm.message = "Test message"; 
    vm.result = null; 
    vm.photosRequest = null; 

    vm.$onInit = function() { 
    vm.message = "Test message"; 
    vm.photosRequest = Photos.getPhotos({}, 
     function(response) { 
     vm.callbackHit = "Good Callback Hit"; 
     vm.result = response; 
     }, 
     function(response) { 
     vm.callbackHit = "Bad Callback Hit (Don't want to see this if $cancelRequest was called, but do if there was an error talking to the server.)" 
     vm.result = response; 
     } 
    ); 
    }; 

    // Simulating a cancel request. How can I tell the error was a cancel and handle differently in the error callback? 
    $timeout(function() { 
    $log.info("cancelling request"); 
    vm.photosRequest.$cancelRequest(); 
    }, 25); 
} 

app.component("myComponent", { 
    templateUrl: "myComponent.html", 
    require: {}, 
    bindings: {}, 
    controller: MyController, 
    controllerAs: "vm" 
}); 

回答

1

你可以做这样的事情:http://plnkr.co/edit/NR9oyXQ8FMdouVAC1Hqx?p=preview

创建一个附加属性来跟踪你的要求:

var vm = this; 
vm.message = "Test message"; 
vm.result = null; 
vm.photosRequest = null; 
// keep track of request state to avoid race conditions 
vm.currentRequest = {id: 0, cancelled: false}; 

当您取消请求时,您更新状态。

vm.photosRequest = Photos.getPhotos({}, 
    response => { 
    if (vm.currentRequest.id == requestNumber) { // ignore old requests resolving late 
     vm.callbackHit = "Good Callback Hit"; 
     vm.result = response; 
    } 
    }, error => { 
    if (vm.currentRequest.id == requestNumber) { // ignore old requests resolving late 
     if (vm.currentRequest.cancelled) { // fail silently 
     $log.info('doing nothing in response to cancelled request'); 
     } else { 
     vm.callbackHit = "Bad Callback Hit (Don't want to see this if $cancelRequest was called, but do if there was an error talking to the server.)" 
     vm.result = error; 
     } 
    } 
    }); 

每次你做一个新的请求,重置状态:

$timeout(function() { 
    $log.info("cancelling request"); 
    vm.photosRequest.$cancelRequest(); 
    vm.currentRequest.cancelled = true; 
}, 25); 

而在你的回调,你决定什么时候做什么检查状态。

var requestNumber = ++vm.currentRequest.id; 
vm.currentRequest.cancelled = false; // reset cancelled state on new request 
vm.photosRequest = Photos.getPhotos({},...) 

这不是最完美的解决方案,但请求状态似乎并没有保持跟踪,如果$ cancelRequest被称为与否,所以你必须保持跟踪自己。

+0

谢谢。我想过这个,但希望有更好的方法来避免它。除非有人在下周提供更好的东西,否则我会将其标记为答案。我只是改变了这些行的顺序:vm.photosRequest。$ cancelRequest(); vm.currentRequest.cancelled = true;这样vm.currentRequest.cancelled = true;来之前。再次感谢。 – PCalouche

+0

是的,我也很想听到更好的解决方案。我也意识到,在提出新请求之前取消请求可能是明智的做法,因此您可以使用类似于 'vm.photosRequest。$ cancelRequest(); vm.photosRequest = Photos.getPhotos({},...);'只要你提出新的请求。 – ppham27

相关问题