$resource 요청을 취소하는 방법
$리소스의 타임아웃 속성을 사용하여 보류 중인 요청을 동적으로 취소하는 방법을 알아보려고 합니다.이상적으로는 (보낸 파라미터에 따라) 특정 속성을 가진 요청을 취소할 수 있으면 좋겠지만, 불가능할 수도 있습니다.그동안 보류 중인 요청을 모두 취소하고 새로운 요청을 허용하도록 타임아웃 약속을 재설정하려고 합니다.
문제는 $resource 설정에서 타임아웃 값에 대해 하나의 정적 약속만 허용한다는 것입니다.개별 $http 콜을 발신하는 경우 타임아웃에 대한 새로운 약속을 전달할 수 있기 때문에 이 작업을 수행하는 것은 의미가 있지만 $리소스로 어떻게 작동합니까?여기에서는, http://plnkr.co/edit/PP2tqDYXh1NAOU3yqCwP?p=preview 의 샘플 플런커를 설정했습니다.
컨트롤러 코드는 다음과 같습니다.
app.controller('MainCtrl', function($scope, $timeout, $q, $resource) {
$scope.canceller = $q.defer();
$scope.pending = 0;
$scope.actions = [];
var API = $resource(
'index.html', {}, {
get: {
method: 'GET',
timeout: $scope.canceller.promise
}
}
)
$scope.fetchData = function() {
if ($scope.pending) {
$scope.abortPending();
}
$scope.pending = 1;
$scope.actions.push('request');
API.get({}, function() {
$scope.actions.push('completed');
$scope.pending = 0;
}, function() {
$scope.actions.push('aborted');
});
}
$scope.abortPending = function() {
$scope.canceller.resolve();
$scope.canceller = $q.defer();
}
});
현재 보류 중인 요청이 있을 때 취소기는 작동하지만 리셋할 수 없을 것 같습니다.한 번 요청이 중단되면 이후의 모든 요청도 취소됩니다.
보류 중인 요청을 취소할 수 있는 것은 (적어도 제가 구축한) 대부분의 웹 응용 프로그램에서 매우 중요한 기능인 것 같기 때문에 제가 뭔가 놓치고 있는 것이 분명합니다.
감사해요.
Gecko IT의 답변은 유효하지만 다음과 같은 이유로 몇 가지 수정이 필요했습니다.
- 리소스를 다시 만들지 않고 리소스 에이잭스 호출을 여러 번 취소할 수 있습니다.
- 리소스 하위 호환성 만들기 - 리소스 팩토리 이외의 애플리케이션(컨트롤러) 코드를 변경할 필요가 없습니다.
- 코드를 JSLint 준거로 하다
이것은 완전한 서비스 팩토리 구현입니다(적절한 모듈 이름만 입력하면 됩니다).
'use strict';
/**
* ResourceFactory creates cancelable resources.
* Work based on: https://stackoverflow.com/a/25448672/1677187
* which is based on: https://developer.rackspace.com/blog/cancelling-ajax-requests-in-angularjs-applications/
*/
/* global array */
angular.module('module_name').factory('ResourceFactory', ['$q', '$resource',
function($q, $resource) {
function abortablePromiseWrap(promise, deferred, outstanding) {
promise.then(function() {
deferred.resolve.apply(deferred, arguments);
});
promise.catch(function() {
deferred.reject.apply(deferred, arguments);
});
/**
* Remove from the outstanding array
* on abort when deferred is rejected
* and/or promise is resolved/rejected.
*/
deferred.promise.finally(function() {
array.remove(outstanding, deferred);
});
outstanding.push(deferred);
}
function createResource(url, options, actions) {
var resource;
var outstanding = [];
actions = actions || {};
Object.keys(actions).forEach(function(action) {
var canceller = $q.defer();
actions[action].timeout = canceller.promise;
actions[action].Canceller = canceller;
});
resource = $resource(url, options, actions);
Object.keys(actions).forEach(function(action) {
var method = resource[action];
resource[action] = function() {
var deferred = $q.defer(),
promise = method.apply(null, arguments).$promise;
abortablePromiseWrap(promise, deferred, outstanding);
return {
$promise: deferred.promise,
abort: function() {
deferred.reject('Aborted');
},
cancel: function() {
actions[action].Canceller.resolve('Call cancelled');
// Recreate canceler so that request can be executed again
var canceller = $q.defer();
actions[action].timeout = canceller.promise;
actions[action].Canceller = canceller;
}
};
};
});
/**
* Abort all the outstanding requests on
* this $resource. Calls promise.reject() on outstanding [].
*/
resource.abortAll = function() {
for (var i = 0; i < outstanding.length; i++) {
outstanding[i].reject('Aborted all');
}
outstanding = [];
};
return resource;
}
return {
createResource: function (url, options, actions) {
return createResource(url, options, actions);
}
};
}
]);
사용법은 Gecko IT의 예시와 동일합니다.서비스 팩토리:
'use strict';
angular.module('module_name').factory('YourResourceServiceName', ['ResourceFactory', function(ResourceFactory) {
return ResourceFactory.createResource('some/api/path/:id', { id: '@id' }, {
create: {
method: 'POST'
},
update: {
method: 'PUT'
}
});
}]);
컨트롤러 사용 현황(후방 호환):
var result = YourResourceServiceName.create(data);
result.$promise.then(function success(data, responseHeaders) {
// Successfully obtained data
}, function error(httpResponse) {
if (httpResponse.status === 0 && httpResponse.data === null) {
// Request has been canceled
} else {
// Server error
}
});
result.cancel(); // Cancels XHR request
대체 접근법:
var result = YourResourceServiceName.create(data);
result.$promise.then(function success(data, responseHeaders) {
// Successfully obtained data
}).catch(function (httpResponse) {
if (httpResponse.status === 0 && httpResponse.data === null) {
// Request has been canceled
} else {
// Server error
}
});
result.cancel(); // Cancels XHR request
기타 개선 사항:
- 나는 요청이 취소되었는지 확인하는 것을 좋아하지 않는다.Atribute를 부가하는 것이 좋습니다.
httpResponse.isCanceled
요청이 취소된 경우 및 중단 시에도 마찬가지입니다.
(각 1.2.28+의 경우)모두 안녕하세요, 저는 단지 그것을 이해하기 쉽게 하고 싶었을 뿐입니다.그 문제를 어떻게 처리했는지는 다음과 같습니다.
여기서 타임아웃 파라미터를 선언합니다.
$scope.stopRequestGetAllQuestions=$q.defer();
그럼 나는 그것을 다음과 같이 사용한다.
return $resource(urlToGet, {}, {get:{ timeout: stopRequestGetAllQuestions.promise }});
이전 $resource 호출을 중지하려면 이 stopRequestGetAllQuestions 개체를 해결하면 됩니다.
stopRequestGetAllQuestions.resolve();
, 이전 $ 콜을 할 경우 $resource 콜 에 이 합니다.stopRequestGetAllQuestions.resolve();
:
stopRequestGetAllQuestions = $q.defer();
현재 세상에는 꽤 많은 예들이 있다.다음 두 가지가 매우 유익하다고 생각합니다.
이 예에서는 $resource 요구와 $resource 요구를 모두 처리하는 방법을 보여 줍니다.https://developer.rackspace.com/blog/cancelling-ajax-requests-in-angularjs-applications/
그리고.
이 제품은 더 심플하고 $1200 전용입니다.http://odetocode.com/blogs/scott/archive/2014/04/24/canceling-http-requests-in-angularjs.aspx
안녕하세요. 저는 https://developer.rackspace.com/blog/을 기반으로 커스텀 핸들러를 만들었습니다.
.factory('ResourceFactory', ["$q", "$resource", function($q, $resource) {
function createResource(url, options, actions) {
var actions = actions || {},
resource,
outstanding = [];
Object.keys(actions).forEach(function (action) {
console.log(actions[action]);
var canceller = $q.defer();
actions[action].timeout = canceller.promise;
actions[action].Canceller = canceller;
});
resource = $resource(url, options, actions);
Object.keys(actions).forEach(function (action) {
var method = resource[action];
resource[action] = function () {
var deferred = $q.defer(),
promise = method.apply(null, arguments).$promise;
abortablePromiseWrap(promise, deferred, outstanding);
return {
promise: deferred.promise,
abort: function () {
deferred.reject('Aborted');
},
cancel: function () {
console.log(actions[action]);
actions[action].Canceller.resolve("Call cancelled");
}
};
};
});
/**
* Abort all the outstanding requests on
* this $resource. Calls promise.reject() on outstanding [].
*/
resource.abortAll = function () {
for (var i = 0; i < outstanding.length; i++) {
outstanding[i].reject('Aborted all');
}
outstanding = [];
};
return resource;
}
return {
createResource: function (url, options, actions) {
return createResource(url, options, actions);
}
}
}])
function abortablePromiseWrap(promise, deferred, outstanding) {
promise.then(function () {
deferred.resolve.apply(deferred, arguments);
});
promise.catch(function () {
deferred.reject.apply(deferred, arguments);
});
/**
* Remove from the outstanding array
* on abort when deferred is rejected
* and/or promise is resolved/rejected.
*/
deferred.promise.finally(function () {
array.remove(outstanding, deferred);
});
outstanding.push(deferred);
}
//Usage SERVICE
factory("ServiceFactory", ["apiBasePath", "$resource", "ResourceFactory", function (apiBasePath, $resource, QiteResourceFactory) {
return ResourceFactory.createResource(apiBasePath + "service/:id", { id: '@id' }, null);
}])
//Usage Controller
var result = ServiceFactory.get();
console.log(result);
result.promise.then(function (data) {
$scope.services = data;
}).catch(function (a) {
console.log("catch", a);
})
//Actually cancels xhr request
result.cancel();
한 가지 해결책은 필요할 때마다 리소스를 다시 설정하는 것입니다.
// for canceling an ajax request
$scope.canceler = $q.defer();
// create a resource
// (we have to re-craete it every time because this is the only
// way to renew the promise)
function getAPI(promise) {
return $resource(
'index.html', {}, {
get: {
method: 'GET',
timeout: promise
}
}
);
}
$scope.fetchData = function() {
// abort previous requests if they are still running
$scope.canceler.resolve();
// create a new canceler
$scope.canceler = $q.defer();
// instead of using "API.get" we use "getAPI().get"
getAPI( $scope.canceler.promise ).get({}, function() {
$scope.actions.push('completed');
$scope.pending = 0;
}, function() {
$scope.actions.push('aborted');
});
}
이 작업을 해결하기 위해 다음과 같은 솔루션에 도달했습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cancel resource</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular-resource.js"></script>
<script>
angular.module("app", ["ngResource"]).
factory(
"services",
["$resource", function($resource)
{
function resolveAction(resolve)
{
if (this.params)
{
this.timeout = this.params.timeout;
this.params.timeout = null;
}
this.then = null;
resolve(this);
}
return $resource(
"http://md5.jsontest.com/",
{},
{
MD5:
{
method: "GET",
params: { text: null },
then: resolveAction
},
});
}]).
controller(
"Test",
["services", "$q", "$timeout", function(services, $q, $timeout)
{
this.value = "Sample text";
this.requestTimeout = 100;
this.call = function()
{
var self = this;
self.result = services.MD5(
{
text: self.value,
timeout: $q(function(resolve)
{
$timeout(resolve, self.requestTimeout);
})
});
}
}]);
</script>
</head>
<body ng-app="app" ng-controller="Test as test">
<label>Text: <input type="text" ng-model="test.value" /></label><br/>
<label>Timeout: <input type="text" ng-model="test.requestTimeout" /></label><br/>
<input type="button" value="call" ng-click="test.call()"/>
<div ng-bind="test.result.md5"></div>
</body>
</html>
구조
- $resource는 액션 정의, 요청 매개 변수 및 데이터를 병합하여 $syslog 요청에 대한 구성 매개 변수를 구축합니다.
- $syslog 요구에 전달된 config 파라미터는 약속과 같은 오브젝트로 취급되기 때문에 설정을 초기화하는 함수를 포함할 수 있습니다.
- 액션의 함수는 파라미터에서 Configuration으로 타임아웃 약속을 전달할 수 있습니다.
자세한 내용은 "Cancel Angularjs 리소스 요청 취소"를 참조하십시오.
언급URL : https://stackoverflow.com/questions/21666960/how-to-cancel-resource-requests
'programing' 카테고리의 다른 글
react-select: 검사기에서 스타일링할 때 드롭다운을 열어두는 방법? (0) | 2023.03.08 |
---|---|
파일 기반 H2 데이터베이스를 사용하도록 스프링 부트를 구성하는 방법 (0) | 2023.03.08 |
스프링 보안:Spring Boot 2.7.0에서 사용되지 않는 Web Security Configurer Adapter (0) | 2023.03.08 |
TypeScript에서 반응 상태 사용 (0) | 2023.03.08 |
스프링 부트:application.properties를 사용하여 로깅 수준을 설정하려면 어떻게 해야 합니까? (0) | 2023.03.08 |