0

Given code like the following:

function webCall() {
    return $http({ method: "POST", 
                       url: "http://destined/to/fail", data: {param1: 1})
                    .success(function(data, status) { return { test: "success!";} } )
                    .error(function (data, status) { 
                               return {errorMessage: "Totally failed!"};
                     });

It is my understanding that if I call .then() on the returned promise like so:

var myPromise = webCall().then(
                               function(response){
                                   console.log(response.test);
                               }, 
                               function(reason) {
                                   console.log(reason.errorMessage); 
                               });

that the returned value from the appropriate .success() and .error() callbacks is passed along to the .then() callbacks.

I am not seeing the behavior I expect however. Using GET it works as expected. With POST, not so much. Is my assumption that it should act like normal deferred \ promise accurate? Where is it documented (other than the source)

Mike Cheel
  • 12,626
  • 10
  • 72
  • 101
  • Your success handler looks like it's missing `return {...}`. Is that just a copy-pasta error? – superEb Jul 17 '14 at 21:19
  • This is pseudo code based on working code that I have. Yea I'll fix it. – Mike Cheel Jul 17 '14 at 21:20
  • should act the same regardless of method – charlietfl Jul 17 '14 at 21:32
  • That's what I am thinking. In my project the GET works like a charm and the POST just passes through what appears to be the same object that was passed to the .success() or .error() callbacks. I'm using 1.2.19 btw. – Mike Cheel Jul 17 '14 at 21:32
  • I normally use `then` instead of success and error methods – charlietfl Jul 17 '14 at 21:33
  • I have a work around for what I am doing BUT I like to know what the real deal is. I'm guess if this is by design then it is because POSTs don't return data typically. – Mike Cheel Jul 17 '14 at 21:34
  • I'm digging deeper and it looks like only the success callback passes the data in (for GET). Return values for GET and POST error() don't seem to get passed into then() (but your then will still be called with the data that was in the .success(). – Mike Cheel Jul 17 '14 at 22:29

2 Answers2

0

$http() returns a promise, but what you're returning is actually the result of .error(), which isn't a promise (at least it's not documented as such).

To return a promise, you have use then()...

function webCall() {
    return $http({ method: "POST", 
                   url: "/destined/to/fail", data: {param1: 1})
            .then(function(response) { 
                // if you need to access the data here, use response.data
                return { test: "success!" };
            }, function (response) { 
                throw { errorMessage: "Totally failed!" };
            });
}

Note the use of throw to reject the returned promise, because if you simply return from the error callback, it actually resolves resulting promise.

Anthony Chu
  • 37,170
  • 10
  • 81
  • 71
  • I understand they are not part of the standard interface BUT they work as expected when using GET. So why is the behavior different when using POST? I don't see mention of it anywhere. – Mike Cheel Jul 17 '14 at 21:35
0

The reason it doesn't work as you expect is because the .success and .error handlers return the original promise and it does nothing with the return value from the success/error handlers. You can see that from the source code for $http here.

  promise.success = function(fn) {
    promise.then(function(response) {
      fn(response.data, response.status, response.headers, config);
    });
    return promise;
  };

You can see that once the promise is resolved (when the web call returns), it will call your sucess handler, and then do nothing with it.

When you chain this with other handlers it is the result of the original promise that is passed along to the other handlers.

Michael Kang
  • 52,003
  • 16
  • 103
  • 135