Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

fix($resource): fix interceptors and success/error callbacks #16446

Closed
wants to merge 4 commits into from

Commits on Feb 20, 2018

  1. fix($resource): fix interceptors and success/error callbacks

    Previously, action-specific interceptors and `success`/`error` callbacks
    were executed in inconsistent relative orders and in a way that did not
    meet the general expectation for interceptor behavior (e.g. ability to
    recover from errors, performing asynchronous operations, etc).
    
    This commit fixes the behavior to make it more consistent and expected.
    The main differences are that `success`/`error` callbacks will now be
    run _after_ `response`/`responseError` interceptors complete (even if
    interceptors return a promise) and the correct callback will be called
    based on the result of the interceptor (e.g. if the `responseError`
    interceptor recovers from an error, the `success` callback will be
    called).
    See also angular#9334 (comment).
    
    This commit also replaces the use of `success`/`error` callbacks in the
    docs with using the returned promise.
    
    Fixes angular#6731
    Fixes angular#9334
    Closes angular#6865
    
    BREAKING CHANGE:
    
    If you are not using `success` or `error` callbacks with `$resource`,
    your app should not be affected by this change.
    
    If you are using `success` or `error` callbacks (with or without
    response interceptors), one (subtle) difference is that throwing an
    error inside the callbacks will not propagate to the returned
    `$promise`. Therefore, you should try to use the promises whenever
    possible. E.g.:
    
    ```js
    // Avoid
    User.query(function onSuccess(users) { throw new Error(); }).
      $promise.
      catch(function onError() { /* Will not be called. */ });
    
    // Prefer
    User.query().
      $promise.
      then(function onSuccess(users) { throw new Error(); }).
      catch(function onError() { /* Will be called. */ });
    ```
    
    Finally, if you are using `success` or `error` callbacks with response
    interceptors, the callbacks will now always run _after_ the interceptors
    (and wait for them to resolve in case they return a promise).
    Previously, the `error` callback was called before the `responseError`
    interceptor and the `success` callback was synchronously called after
    the `response` interceptor. E.g.:
    
    ```js
    var User = $resource('/api/users/:id', {id: '@id'}, {
      get: {
        method: 'get',
        interceptor: {
          response: function(response) {
            console.log('responseInterceptor-1');
            return $timeout(1000).then(function() {
              console.log('responseInterceptor-2');
              return response.resource;
            });
          },
          responseError: function(response) {
            console.log('responseErrorInterceptor-1');
            return $timeout(1000).then(function() {
              console.log('responseErrorInterceptor-2');
              return $q.reject('Ooops!');
            });
          }
        }
      }
    });
    var onSuccess = function(value) { console.log('successCallback', value); };
    var onError = function(error) { console.log('errorCallback', error); };
    
    // Assuming the following call is successful...
    User.get({id: 1}, onSuccess, onError);
      // Old behavior:
      //   responseInterceptor-1
      //   successCallback, {/* Promise object */}
      //   responseInterceptor-2
      // New behavior:
      //   responseInterceptor-1
      //   responseInterceptor-2
      //   successCallback, {/* User object */}
    
    // Assuming the following call returns an error...
    User.get({id: 2}, onSuccess, onError);
      // Old behavior:
      //   errorCallback, {/* Response object */}
      //   responseErrorInterceptor-1
      //   responseErrorInterceptor-2
      // New behavior:
      //   responseErrorInterceptor-1
      //   responseErrorInterceptor-2
      //   errorCallback, Ooops!
    ```
    gkalpak committed Feb 20, 2018
    Configuration menu
    Copy the full SHA
    d9dc7b9 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    f962ce2 View commit details
    Browse the repository at this point in the history
  3. Configuration menu
    Copy the full SHA
    89b8ab1 View commit details
    Browse the repository at this point in the history
  4. Configuration menu
    Copy the full SHA
    a2df3a1 View commit details
    Browse the repository at this point in the history