-
Notifications
You must be signed in to change notification settings - Fork 27.5k
WIP - feat($resource): add support for cancelling requests using promises #13058
WIP - feat($resource): add support for cancelling requests using promises #13058
Conversation
Previously, it was not possible to use a promise as value for the `timeout` property of an action's `config`, because that value would be copied before being passed to `$http`. This commit introduces a special value for the `timeout`, namely `'promise'`. Setting an action's `timeout` configuration property to `'promise'`, will create a new promise and pass it to `$http` for each request. The associated deferred, is attached to the resource instance, under `$timeoutDeferred`. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { query: { method: 'GET', isArray: true, timeout: 'promise' } }); var posts = Post.query(); // GET /posts ... // Later we decide to cancel the request // in order to make a new one posts.$timeoutDeferred.resolve(); posts.query({author: 'me'}); // GET /posts?author=me ... ``` Fixes angular#9332 Closes angular#13050
This is a POC to get some feedback. Still missing/pending (if we decide to move this forward):
|
I'm not qualified to review, but my opinion is that this is an excellent solution! Thanks a lot! |
Not quite (e.g. see #12657 (comment) and next couple of comments). This is adding better support for cancelling resource requests. |
I see! The feature is a good idea. I am not sure of the API, though. |
I don't feel too strongly about the proposed API, but I would rather avoid the boiler plate of having to pass a promise every time (especially if we can easily avoid it :)). I'm definitely open to better ideas though. |
Let's have a think about it. |
Here's another idea (thinking loud):
(I wonder what other libs do. Have to take a look around.) |
@gkalpak I like the sound of that better |
From a quick look to other libs (Restangular, Angular Restmod, ModelCore, angular-restResource), they don't seem to have any special handling in place. |
Good stuff @gkalpak |
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warnign is logged (using `$log.debug()`) and the property is removed. - Add support for a boolean `cancellable` property to actions' configuration, the `$resource` classes `options` of the `$resourceProvider`'s defaults. If true, the `$cancelRequest` method (added to all returned values for non-instance calls) will abort the request (if it's not already completed or aborted). If there is `timeout` specified on the action's configuration, the value of `cancellable` is ignored. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET', cancellable: true } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more currentPost.$cancelRequest(); currentPost = Post.get({id: 2}); ... ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warnign is logged (using `$log.debug()`) and the property is removed. - Add support for a boolean `cancellable` property to actions' configuration, the `$resource` classes `options` of the `$resourceProvider`'s defaults. If true, the `$cancelRequest` method (added to all returned values for non-instance calls) will abort the request (if it's not already completed or aborted). If there is `timeout` specified on the action's configuration, the value of `cancellable` is ignored. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET', cancellable: true } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more currentPost.$cancelRequest(); currentPost = Post.get({id: 2}); ... ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warning is logged (using `$log.debug()`) and the property is removed. - Add support for a boolean `cancellable` property in actions' configuration, the `$resource` factory's `options` parameter and the `$resourceProvider`'s `defaults` property. If true, the `$cancelRequest` method (added to all returned values for non-instance calls) will abort the request (if it's not already completed or aborted). If there is a numeric `timeout` specified on the action's configuration, the value of `cancellable` will be ignored. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET', cancellable: true } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more currentPost.$cancelRequest(); currentPost = Post.get({id: 2}); ... ``` BREAKING CHANGE: Using a promise as `timeout` is no longer supported and will log a warning. It never worked the way it was supposed to anyway. Before: ```js var deferred = $q.defer(); var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', timeout: deferred.promise} }); var user = User.get({id: 1}); // sends a request deferred.resolve(); // aborts the request // Now, we need to re-define `User` passing a new promise as `timeout` // or else all subsequent requests from `someAction` will be aborted User = $resource(...); user = User.get({id: 2}); ``` After: ```js var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', cancellable: true} }); var user = User.get({id: 1}); // sends a request instance.$cancelRequest(); // aborts the request user = User.get({id: 2}); ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warning is logged (using `$log.debug()`) and the property is removed. - Add support for a boolean `cancellable` property in actions' configuration, the `$resource` factory's `options` parameter and the `$resourceProvider`'s `defaults` property. If true, the `$cancelRequest` method (added to all returned values for non-instance calls) will abort the request (if it's not already completed or aborted). If there is a numeric `timeout` specified on the action's configuration, the value of `cancellable` will be ignored. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET', cancellable: true } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more currentPost.$cancelRequest(); currentPost = Post.get({id: 2}); ... ``` BREAKING CHANGE: Using a promise as `timeout` is no longer supported and will log a warning. It never worked the way it was supposed to anyway. Before: ```js var deferred = $q.defer(); var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', timeout: deferred.promise} }); var user = User.get({id: 1}); // sends a request deferred.resolve(); // aborts the request // Now, we need to re-define `User` passing a new promise as `timeout` // or else all subsequent requests from `someAction` will be aborted User = $resource(...); user = User.get({id: 2}); ``` After: ```js var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', cancellable: true} }); var user = User.get({id: 1}); // sends a request instance.$cancelRequest(); // aborts the request user = User.get({id: 2}); ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warning is logged (using `$log.debug()`) and the property is removed. - Provide a `cancelRequest` static method on the Resource that will abort the request (if it's not already completed or aborted). If there is a numeric `timeout` specified on the action's configuration, this method will have no effect. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET' } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more Post.cancelRequest(currentPost); currentPost = Post.get({id: 2}); ... ``` BREAKING CHANGE: Using a promise as `timeout` is no longer supported and will log a warning. It never worked the way it was supposed to anyway. Before: ```js var deferred = $q.defer(); var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', timeout: deferred.promise} }); var user = User.get({id: 1}); // sends a request deferred.resolve(); // aborts the request // Now, we need to re-define `User` passing a new promise as `timeout` // or else all subsequent requests from `someAction` will be aborted User = $resource(...); user = User.get({id: 2}); ``` After: ```js var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET'} }); var user = User.get({id: 1}); // sends a request User.cancelRequest(instance); // aborts the request user = User.get({id: 2}); ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Introduced changes: - Deprecate passing a promise as `timeout` (for `$resource` actions). It never worked correctly anyway. Now a warning is logged (using `$log.debug()`) and the property is removed. - Provide a `cancelRequest` static method on the Resource that will abort the request (if it's not already completed or aborted). If there is a numeric `timeout` specified on the action's configuration, this method will have no effect. Example usage: ```js var Post = $resource('/posts/:id', {id: '@id'}, { get: { method: 'GET' } }); var currentPost = Post.get({id: 1}); ... // A moment later the user selects another post, so // we don't need the previous request any more Post.cancelRequest(currentPost); currentPost = Post.get({id: 2}); ... ``` BREAKING CHANGE: Using a promise as `timeout` is no longer supported and will log a warning. It never worked the way it was supposed to anyway. Before: ```js var deferred = $q.defer(); var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET', timeout: deferred.promise} }); var user = User.get({id: 1}); // sends a request deferred.resolve(); // aborts the request // Now, we need to re-define `User` passing a new promise as `timeout` // or else all subsequent requests from `someAction` will be aborted User = $resource(...); user = User.get({id: 2}); ``` After: ```js var User = $resource('/api/user/:id', {id: '@id'}, { get: {method: 'GET'} }); var user = User.get({id: 1}); // sends a request User.cancelRequest(instance); // aborts the request user = User.get({id: 2}); ``` Fixes angular#9332 Closes angular#13050 Closes angular#13058
Previously, it was not possible to use a promise as value for the
timeout
property of an action'sconfig
, because that value would be copied before being passed to$http
.This commit introduces a special value for the
timeout
, namely'promise'
.Setting an action's
timeout
configuration property to'promise'
, will create a new promise and pass it to$http
for each request. The associated deferred, is attached to the resource instance, under$timeoutDeferred
.Example usage:
Fixes #9332
Closes #13050