diff options
Diffstat (limited to 'src/ngResource/resource.js')
| -rw-r--r-- | src/ngResource/resource.js | 126 | 
1 files changed, 66 insertions, 60 deletions
| diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index 59ac3b3a..abb2bc56 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -92,6 +92,9 @@   *     requests with credentials} for more information.   *   - **`responseType`** - `{string}` - see {@link   *     https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. + *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - + *     `response` and `responseError`. Both `response` and `responseError` interceptors get called + *     with `http response` object. See {@link ng.$http $http interceptors}.   *   * @returns {Object} A resource "class" object with methods for the default set of resource actions   *   optionally extended with custom `actions`. The default set contains these actions: @@ -130,24 +133,27 @@   *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`   *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`   * + *   Success callback is called with (value, responseHeaders) arguments. Error callback is called + *   with (httpResponse) argument.   * - *   The Resource instances and collection have these additional properties: + *   Class actions return empty instance (with additional properties below). + *   Instance actions return promise of the action.   * - *   - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying - *     {@link ng.$http $http} call. + *   The Resource instances and collection have these additional properties:   * - *     The success callback for the `$then` method will be resolved if the underlying `$http` requests - *     succeeds. + *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this + *     instance or collection.   * - *     The success callback is called with a single object which is the {@link ng.$http http response} - *     object extended with a new property `resource`. This `resource` property is a reference to the - *     result of the resource action — resource object or array of resources. + *     On success, the promise is resolved with the same resource instance or collection object, + *     updated with data from server. This makes it easy to use in + *     {@link ng.$routeProvider resolve section of $routeProvider.when()} to defer view rendering + *     until the resource(s) are loaded.   * - *     The error callback is called with the {@link ng.$http http response} object when an http - *     error occurs. + *     On failure, the promise is resolved with the {@link ng.$http http response} object, + *     without the `resource` property.   * - *   - `$resolved`: true if the promise has been resolved (either with success or rejection); - *     Knowing if the Resource has been resolved is useful in data-binding. + *   - `$resolved`: `true` after first server interaction is completed (either with success or rejection), + *     `false` before that. Knowing if the Resource has been resolved is useful in data-binding.   *   * @example   * @@ -268,7 +274,7 @@      </doc:example>   */  angular.module('ngResource', ['ng']). -  factory('$resource', ['$http', '$parse', function($http, $parse) { +  factory('$resource', ['$http', '$parse', '$q', function($http, $parse, $q) {      var DEFAULT_ACTIONS = {        'get':    {method:'GET'},        'save':   {method:'POST'}, @@ -398,19 +404,19 @@ angular.module('ngResource', ['ng']).          return ids;        } +      function defaultResponseInterceptor(response) { +        return response.resource; +      } +        function Resource(value){          copy(value || {}, this);        }        forEach(actions, function(action, name) { -        action.method = angular.uppercase(action.method); -        var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH'; +        var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); +          Resource[name] = function(a1, a2, a3, a4) { -          var params = {}; -          var data; -          var success = noop; -          var error = null; -          var promise; +          var params = {}, data, success, error;            switch(arguments.length) {            case 4: @@ -442,31 +448,28 @@ angular.module('ngResource', ['ng']).              break;            case 0: break;            default: -            throw "Expected between 0-4 arguments [params, data, success, error], got " + +            throw "Expected up to 4 arguments [params, data, success, error], got " +                arguments.length + " arguments.";            } -          var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data)); -          var httpConfig = {}, -              promise; +          var isInstanceCall = data instanceof Resource; +          var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); +          var httpConfig = {}; +          var responseInterceptor = action.interceptor && action.interceptor.response || defaultResponseInterceptor; +          var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || undefined;            forEach(action, function(value, key) { -            if (key != 'params' && key != 'isArray' ) { +            if (key != 'params' && key != 'isArray' && key != 'interceptor') {                httpConfig[key] = copy(value);              }            }); +            httpConfig.data = data;            route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url); -          function markResolved() { value.$resolved = true; } - -          promise = $http(httpConfig); -          value.$resolved = false; - -          promise.then(markResolved, markResolved); -          value.$then = promise.then(function(response) { -            var data = response.data; -            var then = value.$then, resolved = value.$resolved; +          var promise = $http(httpConfig).then(function(response) { +            var data = response.data, +                promise = value.$promise;              if (data) {                if (action.isArray) { @@ -476,44 +479,47 @@ angular.module('ngResource', ['ng']).                  });                } else {                  copy(data, value); -                value.$then = then; -                value.$resolved = resolved; +                value.$promise = promise;                }              } +            value.$resolved = true; +              (success||noop)(value, response.headers);              response.resource = value; +              return response; -          }, error).then; +          }, function(response) { +            value.$resolved = true; -          return value; -        }; +            (error||noop)(response); +            return $q.reject(response); +          }).then(responseInterceptor, responseErrorInterceptor); -        Resource.prototype['$' + name] = function(a1, a2, a3) { -          var params = extractParams(this), -              success = noop, -              error; -          switch(arguments.length) { -          case 3: params = a1; success = a2; error = a3; break; -          case 2: -          case 1: -            if (isFunction(a1)) { -              success = a1; -              error = a2; -            } else { -              params = a1; -              success = a2 || noop; -            } -          case 0: break; -          default: -            throw "Expected between 1-3 arguments [params, success, error], got " + -              arguments.length + " arguments."; +          if (!isInstanceCall) { +            // we are creating instance / collection +            // - set the initial promise +            // - return the instance / collection +            value.$promise = promise; +            value.$resolved = false; + +            return value; +          } + +          // instance call +          return promise; +        }; + + +        Resource.prototype['$' + name] = function(params, success, error) { +          if (isFunction(params)) { +            error = success; success = params; params = {};            } -          var data = hasBody ? this : undefined; -          Resource[name].call(this, params, data, success, error); +          var result = Resource[name](params, this, success, error); +          return result.$promise || result;          };        }); | 
