2016-12-28 73 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

相關問題