92
92
* requests with credentials} for more information.
93
93
* - **`responseType`** - `{string}` - see {@link
94
94
* https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
95
+ * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
96
+ * `response` and `responseError`. Both `response` and `responseError` interceptors get called
97
+ * with `http response` object. See {@link ng.$http $http interceptors}.
95
98
*
96
99
* @returns {Object } A resource "class" object with methods for the default set of resource actions
97
100
* optionally extended with custom `actions`. The default set contains these actions:
130
133
* - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
131
134
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
132
135
*
136
+ * Success callback is called with (value, responseHeaders) arguments. Error callback is called
137
+ * with (httpResponse) argument.
133
138
*
134
- * The Resource instances and collection have these additional properties:
139
+ * Class actions return empty instance (with additional properties below).
140
+ * Instance actions return promise of the action.
135
141
*
136
- * - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying
137
- * {@link ng.$http $http} call.
142
+ * The Resource instances and collection have these additional properties:
138
143
*
139
- * The success callback for the `$then` method will be resolved if the underlying `$http` requests
140
- * succeeds .
144
+ * - `$promise`: the { @link ng.$q promise} of the original server interaction that created this
145
+ * instance or collection .
141
146
*
142
- * The success callback is called with a single object which is the {@link ng.$http http response}
143
- * object extended with a new property `resource`. This `resource` property is a reference to the
144
- * result of the resource action — resource object or array of resources.
147
+ * On success, the promise is resolved with the same resource instance or collection object,
148
+ * updated with data from server. This makes it easy to use in
149
+ * {@link ng.$routeProvider resolve section of $routeProvider.when()} to defer view rendering
150
+ * until the resource(s) are loaded.
145
151
*
146
- * The error callback is called with the {@link ng.$http http response} object when an http
147
- * error occurs .
152
+ * On failure, the promise is resolved with the {@link ng.$http http response} object,
153
+ * without the `resource` property .
148
154
*
149
- * - `$resolved`: true if the promise has been resolved (either with success or rejection);
150
- * Knowing if the Resource has been resolved is useful in data-binding.
155
+ * - `$resolved`: ` true` after first server interaction is completed (either with success or rejection),
156
+ * `false` before that. Knowing if the Resource has been resolved is useful in data-binding.
151
157
*
152
158
* @example
153
159
*
268
274
</doc:example>
269
275
*/
270
276
angular . module ( 'ngResource' , [ 'ng' ] ) .
271
- factory ( '$resource' , [ '$http' , '$parse' , function ( $http , $parse ) {
277
+ factory ( '$resource' , [ '$http' , '$parse' , '$q' , function ( $http , $parse , $q ) {
272
278
var DEFAULT_ACTIONS = {
273
279
'get' : { method :'GET' } ,
274
280
'save' : { method :'POST' } ,
@@ -398,19 +404,19 @@ angular.module('ngResource', ['ng']).
398
404
return ids ;
399
405
}
400
406
407
+ function defaultResponseInterceptor ( response ) {
408
+ return response . resource ;
409
+ }
410
+
401
411
function Resource ( value ) {
402
412
copy ( value || { } , this ) ;
403
413
}
404
414
405
415
forEach ( actions , function ( action , name ) {
406
- action . method = angular . uppercase ( action . method ) ;
407
- var hasBody = action . method == 'POST' || action . method == 'PUT' || action . method == 'PATCH' ;
416
+ var hasBody = / ^ ( P O S T | P U T | P A T C H ) $ / i . test ( action . method ) ;
417
+
408
418
Resource [ name ] = function ( a1 , a2 , a3 , a4 ) {
409
- var params = { } ;
410
- var data ;
411
- var success = noop ;
412
- var error = null ;
413
- var promise ;
419
+ var params = { } , data , success , error ;
414
420
415
421
switch ( arguments . length ) {
416
422
case 4 :
@@ -442,31 +448,28 @@ angular.module('ngResource', ['ng']).
442
448
break ;
443
449
case 0 : break ;
444
450
default :
445
- throw "Expected between 0- 4 arguments [params, data, success, error], got " +
451
+ throw "Expected up to 4 arguments [params, data, success, error], got " +
446
452
arguments . length + " arguments." ;
447
453
}
448
454
449
- var value = this instanceof Resource ? this : ( action . isArray ? [ ] : new Resource ( data ) ) ;
450
- var httpConfig = { } ,
451
- promise ;
455
+ var isInstanceCall = data instanceof Resource ;
456
+ var value = isInstanceCall ? data : ( action . isArray ? [ ] : new Resource ( data ) ) ;
457
+ var httpConfig = { } ;
458
+ var responseInterceptor = action . interceptor && action . interceptor . response || defaultResponseInterceptor ;
459
+ var responseErrorInterceptor = action . interceptor && action . interceptor . responseError || undefined ;
452
460
453
461
forEach ( action , function ( value , key ) {
454
- if ( key != 'params' && key != 'isArray' ) {
462
+ if ( key != 'params' && key != 'isArray' && key != 'interceptor' ) {
455
463
httpConfig [ key ] = copy ( value ) ;
456
464
}
457
465
} ) ;
466
+
458
467
httpConfig . data = data ;
459
468
route . setUrlParams ( httpConfig , extend ( { } , extractParams ( data , action . params || { } ) , params ) , action . url ) ;
460
469
461
- function markResolved ( ) { value . $resolved = true ; }
462
-
463
- promise = $http ( httpConfig ) ;
464
- value . $resolved = false ;
465
-
466
- promise . then ( markResolved , markResolved ) ;
467
- value . $then = promise . then ( function ( response ) {
468
- var data = response . data ;
469
- var then = value . $then , resolved = value . $resolved ;
470
+ var promise = $http ( httpConfig ) . then ( function ( response ) {
471
+ var data = response . data ,
472
+ promise = value . $promise ;
470
473
471
474
if ( data ) {
472
475
if ( action . isArray ) {
@@ -476,44 +479,47 @@ angular.module('ngResource', ['ng']).
476
479
} ) ;
477
480
} else {
478
481
copy ( data , value ) ;
479
- value . $then = then ;
480
- value . $resolved = resolved ;
482
+ value . $promise = promise ;
481
483
}
482
484
}
483
485
486
+ value . $resolved = true ;
487
+
484
488
( success || noop ) ( value , response . headers ) ;
485
489
486
490
response . resource = value ;
491
+
487
492
return response ;
488
- } , error ) . then ;
493
+ } , function ( response ) {
494
+ value . $resolved = true ;
489
495
490
- return value ;
491
- } ;
496
+ ( error || noop ) ( response ) ;
492
497
498
+ return $q . reject ( response ) ;
499
+ } ) . then ( responseInterceptor , responseErrorInterceptor ) ;
493
500
494
- Resource . prototype [ '$' + name ] = function ( a1 , a2 , a3 ) {
495
- var params = extractParams ( this ) ,
496
- success = noop ,
497
- error ;
498
501
499
- switch ( arguments . length ) {
500
- case 3 : params = a1 ; success = a2 ; error = a3 ; break ;
501
- case 2 :
502
- case 1 :
503
- if ( isFunction ( a1 ) ) {
504
- success = a1 ;
505
- error = a2 ;
506
- } else {
507
- params = a1 ;
508
- success = a2 || noop ;
509
- }
510
- case 0 : break ;
511
- default :
512
- throw "Expected between 1-3 arguments [params, success, error], got " +
513
- arguments . length + " arguments." ;
502
+ if ( ! isInstanceCall ) {
503
+ // we are creating instance / collection
504
+ // - set the initial promise
505
+ // - return the instance / collection
506
+ value . $promise = promise ;
507
+ value . $resolved = false ;
508
+
509
+ return value ;
510
+ }
511
+
512
+ // instance call
513
+ return promise ;
514
+ } ;
515
+
516
+
517
+ Resource . prototype [ '$' + name ] = function ( params , success , error ) {
518
+ if ( isFunction ( params ) ) {
519
+ error = success ; success = params ; params = { } ;
514
520
}
515
- var data = hasBody ? this : undefined ;
516
- Resource [ name ] . call ( this , params , data , success , error ) ;
521
+ var result = Resource [ name ] ( params , this , success , error ) ;
522
+ return result . $promise || result ;
517
523
} ;
518
524
} ) ;
519
525
0 commit comments