Đưa ra yêu cầu Ajax trong AngularJS
$http.get("/backend/").success(callback);
cách hiệu quả nhất để hủy yêu cầu đó nếu một yêu cầu khác được đưa ra (ví dụ như phụ trợ, các tham số khác nhau).
promise.abort()
stackoverflow.com/a/50415480/984780
Đưa ra yêu cầu Ajax trong AngularJS
$http.get("/backend/").success(callback);
cách hiệu quả nhất để hủy yêu cầu đó nếu một yêu cầu khác được đưa ra (ví dụ như phụ trợ, các tham số khác nhau).
promise.abort()
stackoverflow.com/a/50415480/984780
Câu trả lời:
Tính năng này đã được thêm vào bản phát hành 1.1.5 thông qua thời gian chờ:
var canceler = $q.defer();
$http.get('/someUrl', {timeout: canceler.promise}).success(successCallback);
// later...
canceler.resolve(); // Aborts the $http request if it isn't finished.
setTimeout
chức năng gốc của JavaScript hoặc $timeout
dịch vụ của Angular .
Hủy bỏ Angular $ http Ajax với thuộc tính hết thời gian không hoạt động trong Angular 1.3.15. Đối với những người không thể chờ đợi để sửa lỗi này, tôi đang chia sẻ giải pháp jQuery Ajax được gói trong Angular.
Giải pháp liên quan đến hai dịch vụ:
Ở đây có dịch vụ PendingRequestsService:
(function (angular) {
'use strict';
var app = angular.module('app');
app.service('PendingRequestsService', ["$log", function ($log) {
var $this = this;
var pending = [];
$this.add = function (request) {
pending.push(request);
};
$this.remove = function (request) {
pending = _.filter(pending, function (p) {
return p.url !== request;
});
};
$this.cancelAll = function () {
angular.forEach(pending, function (p) {
p.xhr.abort();
p.deferred.reject();
});
pending.length = 0;
};
}]);})(window.angular);
Dịch vụ httpService:
(function (angular) {
'use strict';
var app = angular.module('app');
app.service('HttpService', ['$http', '$q', "$log", 'PendingRequestsService', function ($http, $q, $log, pendingRequests) {
this.post = function (url, params) {
var deferred = $q.defer();
var xhr = $.ASI.callMethod({
url: url,
data: params,
error: function() {
$log.log("ajax error");
}
});
pendingRequests.add({
url: url,
xhr: xhr,
deferred: deferred
});
xhr.done(function (data, textStatus, jqXhr) {
deferred.resolve(data);
})
.fail(function (jqXhr, textStatus, errorThrown) {
deferred.reject(errorThrown);
}).always(function (dataOrjqXhr, textStatus, jqXhrErrorThrown) {
//Once a request has failed or succeeded, remove it from the pending list
pendingRequests.remove(url);
});
return deferred.promise;
}
}]);
})(window.angular);
Sau này trong dịch vụ của bạn khi bạn đang tải dữ liệu, bạn sẽ sử dụng Dịch vụ httpS thay vì $ http:
(function (angular) {
angular.module('app').service('dataService', ["HttpService", function (httpService) {
this.getResources = function (params) {
return httpService.post('/serverMethod', { param: params });
};
}]);
})(window.angular);
Sau đó trong mã của bạn, bạn muốn tải dữ liệu:
(function (angular) {
var app = angular.module('app');
app.controller('YourController', ["DataService", "PendingRequestsService", function (httpService, pendingRequestsService) {
dataService
.getResources(params)
.then(function (data) {
// do stuff
});
...
// later that day cancel requests
pendingRequestsService.cancelAll();
}]);
})(window.angular);
Hủy bỏ các yêu cầu được ban hành $http
không được hỗ trợ với phiên bản hiện tại của AngularJS. Có một yêu cầu kéo được mở để thêm khả năng này nhưng PR này chưa được xem xét nên chưa rõ liệu nó có biến nó thành lõi AngularJS hay không.
Nếu bạn muốn hủy các yêu cầu đang chờ xử lý trên stateChangeStart bằng ui-router, bạn có thể sử dụng một cái gì đó như thế này:
// phục vụ
var deferred = $q.defer();
var scope = this;
$http.get(URL, {timeout : deferred.promise, cancel : deferred}).success(function(data){
//do something
deferred.resolve(dataUsage);
}).error(function(){
deferred.reject();
});
return deferred.promise;
// trong cấu hình UIrouter
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
//To cancel pending request when change state
angular.forEach($http.pendingRequests, function(request) {
if (request.cancel && request.timeout) {
request.cancel.resolve();
}
});
});
request.timeout
có?
Vì một số lý do config.timeout không hoạt động với tôi. Tôi đã sử dụng phương pháp này:
let cancelRequest = $q.defer();
let cancelPromise = cancelRequest.promise;
let httpPromise = $http.get(...);
$q.race({ cancelPromise, httpPromise })
.then(function (result) {
...
});
Và hủyRequest.resolve () để hủy. Trên thực tế, nó không hủy yêu cầu nhưng ít nhất bạn không nhận được phản hồi không cần thiết.
Hi vọng điêu nay co ich.
{ cancelPromise, httpPromise }
?
Điều này giúp tăng cường câu trả lời được chấp nhận bằng cách trang trí dịch vụ $ http bằng phương pháp hủy bỏ như sau ...
'use strict';
angular.module('admin')
.config(["$provide", function ($provide) {
$provide.decorator('$http', ["$delegate", "$q", function ($delegate, $q) {
var getFn = $delegate.get;
var cancelerMap = {};
function getCancelerKey(method, url) {
var formattedMethod = method.toLowerCase();
var formattedUrl = encodeURI(url).toLowerCase().split("?")[0];
return formattedMethod + "~" + formattedUrl;
}
$delegate.get = function () {
var cancelerKey, canceler, method;
var args = [].slice.call(arguments);
var url = args[0];
var config = args[1] || {};
if (config.timeout == null) {
method = "GET";
cancelerKey = getCancelerKey(method, url);
canceler = $q.defer();
cancelerMap[cancelerKey] = canceler;
config.timeout = canceler.promise;
args[1] = config;
}
return getFn.apply(null, args);
};
$delegate.abort = function (request) {
console.log("aborting");
var cancelerKey, canceler;
cancelerKey = getCancelerKey(request.method, request.url);
canceler = cancelerMap[cancelerKey];
if (canceler != null) {
console.log("aborting", cancelerKey);
if (request.timeout != null && typeof request.timeout !== "number") {
canceler.resolve();
delete cancelerMap[cancelerKey];
}
}
};
return $delegate;
}]);
}]);
MÃ NÀY LÀM GÌ?
Để hủy yêu cầu, thời gian chờ "lời hứa" phải được đặt. Nếu không có thời gian chờ nào được đặt trên yêu cầu HTTP thì mã sẽ thêm thời gian chờ "lời hứa". (Nếu thời gian chờ đã được đặt thì không có gì thay đổi).
Tuy nhiên, để giải quyết lời hứa, chúng tôi cần xử lý "hoãn lại". Do đó, chúng tôi sử dụng bản đồ để có thể truy xuất "hoãn lại" sau. Khi chúng tôi gọi phương thức hủy bỏ, "hoãn lại" được lấy từ bản đồ và sau đó chúng tôi gọi phương thức giải quyết để hủy yêu cầu http.
Hy vọng điều này sẽ giúp được ai đó.
GIỚI HẠN
Hiện tại, điều này chỉ hoạt động với $ http.get nhưng bạn có thể thêm mã cho $ http.post, v.v.
CÁCH SỬ DỤNG ...
Sau đó, bạn có thể sử dụng nó, ví dụ, về thay đổi trạng thái, như sau ...
rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
angular.forEach($http.pendingRequests, function (request) {
$http.abort(request);
});
});
đây là phiên bản xử lý nhiều yêu cầu, đồng thời kiểm tra trạng thái bị hủy trong cuộc gọi lại để loại bỏ lỗi trong khối lỗi. (trong Bản đánh máy)
cấp điều khiển:
requests = new Map<string, ng.IDeferred<{}>>();
trong http của tôi nhận được:
getSomething(): void {
let url = '/api/someaction';
this.cancel(url); // cancel if this url is in progress
var req = this.$q.defer();
this.requests.set(url, req);
let config: ng.IRequestShortcutConfig = {
params: { id: someId}
, timeout: req.promise // <--- promise to trigger cancellation
};
this.$http.post(url, this.getPayload(), config).then(
promiseValue => this.updateEditor(promiseValue.data as IEditor),
reason => {
// if legitimate exception, show error in UI
if (!this.isCancelled(req)) {
this.showError(url, reason)
}
},
).finally(() => { });
}
phương pháp trợ giúp
cancel(url: string) {
this.requests.forEach((req,key) => {
if (key == url)
req.resolve('cancelled');
});
this.requests.delete(url);
}
isCancelled(req: ng.IDeferred<{}>) {
var p = req.promise as any; // as any because typings are missing $$state
return p.$$state && p.$$state.value == 'cancelled';
}
Bây giờ nhìn vào tab mạng, tôi thấy rằng nó hoạt động rất tốt. tôi đã gọi phương thức này 4 lần và chỉ có lần cuối cùng đi qua.
Bạn có thể thêm chức năng tùy chỉnh vào $http
dịch vụ bằng cách sử dụng "trình trang trí" sẽ thêm abort()
chức năng vào lời hứa của bạn.
Đây là một số mã làm việc:
app.config(function($provide) {
$provide.decorator('$http', function $logDecorator($delegate, $q) {
$delegate.with_abort = function(options) {
let abort_defer = $q.defer();
let new_options = angular.copy(options);
new_options.timeout = abort_defer.promise;
let do_throw_error = false;
let http_promise = $delegate(new_options).then(
response => response,
error => {
if(do_throw_error) return $q.reject(error);
return $q(() => null); // prevent promise chain propagation
});
let real_then = http_promise.then;
let then_function = function () {
return mod_promise(real_then.apply(this, arguments));
};
function mod_promise(promise) {
promise.then = then_function;
promise.abort = (do_throw_error_param = false) => {
do_throw_error = do_throw_error_param;
abort_defer.resolve();
};
return promise;
}
return mod_promise(http_promise);
}
return $delegate;
});
});
Mã này sử dụng chức năng trang trí của angularjs để thêm with_abort()
chức năng cho $http
dịch vụ.
with_abort()
sử dụng $http
tùy chọn thời gian chờ cho phép bạn hủy bỏ yêu cầu http.
Lời hứa trả lại được sửa đổi để bao gồm một abort()
chức năng. Nó cũng có mã để đảm bảo rằng các abort()
công trình ngay cả khi bạn hứa hẹn chuỗi.
Đây là một ví dụ về cách bạn sẽ sử dụng nó:
// your original code
$http({ method: 'GET', url: '/names' }).then(names => {
do_something(names));
});
// new code with ability to abort
var promise = $http.with_abort({ method: 'GET', url: '/names' }).then(
function(names) {
do_something(names));
});
promise.abort(); // if you want to abort
Theo mặc định khi bạn gọi abort()
yêu cầu bị hủy và không có trình xử lý lời hứa nào chạy.
Nếu bạn muốn xử lý lỗi của bạn được gọi là pass true abort(true)
.
Trong trình xử lý lỗi của bạn, bạn có thể kiểm tra xem "lỗi" có phải là do "hủy bỏ" hay không bằng cách kiểm tra thuộc xhrStatus
tính. Đây là một ví dụ:
var promise = $http.with_abort({ method: 'GET', url: '/names' }).then(
function(names) {
do_something(names));
},
function(error) {
if (er.xhrStatus === "abort") return;
});