179

According to AngularJS doc, calls to $http return the following:

Returns a promise object with the standard then method and two http specific methods: success and error. The then method takes two arguments a success and an error callback which will be called with a response object. The success and error methods take a single argument - a function that will be called when the request succeeds or fails respectively. The arguments passed into these functions are destructured representation of the response object passed into the then method.

Aside from the fact that the response object is destructured in one case, I don't get the difference between

  • the success/error callbacks passed to be passed as arguments of promise.then
  • the callbacks passed as arguments for the promise.success/promise.error methods of the promise

Is there any? What's the point of these two different ways to pass seemingly identical callbacks?

ejoubaud
  • 5,013
  • 6
  • 37
  • 39

6 Answers6

204

There are some good answers here already. But it's worthwhile to drive home the difference in parallelism offered:

  • success() returns the original promise
  • then() returns a new promise

The difference is then() drives sequential operations, since each call returns a new promise.

$http.get(/*...*/).
  then(function seqFunc1(response){/*...*/}).
  then(function seqFunc2(response){/*...*/})
  1. $http.get()
  2. seqFunc1()
  3. seqFunc2()

success() drives parallel operations, since handlers are chained on the same promise.

$http(/*...*/).
  success(function parFunc1(data){/*...*/}).
  success(function parFunc2(data){/*...*/})
  1. $http.get()
  2. parFunc1(), parFunc2() in parallel
event_jr
  • 17,467
  • 4
  • 47
  • 62
  • 3
    Note the new promise response returned once a `then` is reached results in the `success` and `error` methods disappearing. Also, for http error responses (eg 404) the first `then` in `http.then(ok, err).then(ok, err)` will pass to the `err` handler but the following ones will pass into the `ok` handler. Basically `http.success().error().success().error()` are chainable but $q promises are quite different in that they're all about the promise and sequence of handling specifically (and not http request handling). I had a hard time understanding this until I took close look. – jimmont Sep 17 '14 at 05:50
  • 1
    @jimmont `success` and `error` are not normal API of a promise, they are bolted onto the return value of $http(). – event_jr Sep 18 '14 at 14:46
  • Thanks @event_jr this is clear to me, and called out in the docs. What wasn't as clear (to me) is how $q and $http solve different problems as well as returning new promises vs passing the same one through--as pointed out in your (super helpful) answer. – jimmont Sep 18 '14 at 16:43
  • 1
    What do you mean by parallel, since JS is single-threaded? Do you mean that the execution order is non-deterministic? – Derek Mar 03 '15 at 20:12
  • 2
    @Derek the second `success` will execute after the first one has executed but before any promise returned from it is resolved whereas the second `then` will wait. If you're not returning promises then both behave the same. – Tamlyn Mar 31 '15 at 13:57
  • what does the then() function with one callback function do? only call the callback when success? – Benny May 05 '15 at 08:17
  • Success/Error have now been deprecated. I think of that as a good thing. Here is a summary of some of the downsides to success: http://www.syntaxsuccess.com/viewarticle/angular-promises%E2%80%93then-vs-success – TGH Aug 05 '15 at 01:26
157

NB This answer is factually incorrect; as pointed out by a comment below, success() does return the original promise. I'll not change; and leave it to OP to edit.


The major difference between the 2 is that .then() call returns a promise (resolved with a value returned from a callback) while .success() is more traditional way of registering callbacks and doesn't return a promise.

Promise-based callbacks (.then()) make it easy to chain promises (do a call, interpret results and then do another call, interpret results, do yet another call etc.).

The .success() method is a streamlined, convenience method when you don't need to chain call nor work with the promise API (for example, in routing).

In short:

  • .then() - full power of the promise API but slightly more verbose
  • .success() - doesn't return a promise but offeres slightly more convienient syntax
event_jr
  • 17,467
  • 4
  • 47
  • 62
pkozlowski.opensource
  • 117,202
  • 60
  • 326
  • 286
  • 45
    Another big difference is that the `then` callbacks take a single argument--the response--while `success` and `error` take individual components of the response as arguments--`data`, `status`, `header`, and `config`. – Michelle Tilley May 05 '13 at 18:00
  • 1
    @BrandonTilley totally right, but the author of the question figured it out already so I didn't feel like I need to repeat it here. – pkozlowski.opensource May 05 '13 at 18:02
  • 45
    Although the documentation doesn't say so explicitly, we can infer that the `.success()` method returns the original $http promise object, as the chain `$http(...).success(...).error(...)` is possible. If, as seems reasonable, the inverse `$http(...).error(...).success(...)` is also possible, then `.error()` should also return the original promise object. The distinguishing difference of `.then()` is that it returns a *new* promise. – Beetroot-Beetroot May 05 '13 at 22:55
  • Ok, so both methods do the same thing but offer slightly different chaining options. pkozlowski's answer + Beetroot's correction seems to be the correct answer. So that I can accept an answer, pkozlowski, can you correct yours? Or Beetroot, make one of your own? – ejoubaud May 06 '13 at 07:19
  • 3
    Source code from angular.js of $http service: `promise.success = function(fn) { promise.then(function(response) { fn(response.data, response.status, response.headers, config); }); return promise; };` – Alex Che Nov 28 '13 at 09:51
  • The same source code for the error function: promise.error = function(fn) { promise.then(null, function(response) { fn(response.data, response.status, response.headers, config); }); return promise; }; so it returns the promise – David Michael Gang Nov 02 '14 at 10:12
  • 7
    Please note that `success` has been deprecated. From https://docs.angularjs.org/api/ng/service/$http#deprecation-notice `The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.` – Sam Barnum Feb 17 '16 at 19:56
114

Some code examples for simple GET request. Maybe this helps understanding the difference. Using then:

$http.get('/someURL').then(function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // success handler
}, function(response) {
    var data = response.data,
        status = response.status,
        header = response.header,
        config = response.config;
    // error handler
});

Using success/error:

$http.get('/someURL').success(function(data, status, header, config) {
    // success handler
}).error(function(data, status, header, config) {
    // error handler
});
event_jr
  • 17,467
  • 4
  • 47
  • 62
TheHippo
  • 61,720
  • 15
  • 75
  • 100
  • 5
    Thank you, but the question was more about the difference in what these functions do or the reason why they both exist if they do the same thing. The difference in how to use them is understandable from the doc. – ejoubaud May 06 '13 at 07:14
  • 39
    I personally like short code examples, and that's I posted them here. The Angular docs sometimes miss out on short precise examples. – TheHippo May 06 '13 at 11:38
  • 2
    It's important highlight the fact that the respond object of the first gist contains "data, status, heade and config" of second gist. That means that respond objects has one level aditional of depth. – geoom May 22 '14 at 07:04
  • Is there any benefit of passing the response values to variables `data,status,header,config` over simply returning `response`? – ᴍᴀᴛᴛ ʙᴀᴋᴇʀ Nov 24 '15 at 13:58
27

.then() is chainable and will wait for previous .then() to resolve.

.success() and .error() can be chained, but they will all fire at once (so not much point to that)

.success() and .error() are just nice for simple calls (easy makers):

$http.post('/getUser').success(function(user){ 
   ... 
})

so you don't have to type this:

$http.post('getUser').then(function(response){
  var user = response.data;
})

But generally i handler all errors with .catch():

$http.get(...)
    .then(function(response){ 
      // successHandler
      // do some stuff
      return $http.get('/somethingelse') // get more data
    })
    .then(anotherSuccessHandler)
    .catch(errorHandler)

If you need to support <= IE8 then write your .catch() and .finally() like this (reserved methods in IE):

    .then(successHandler)
    ['catch'](errorHandler)

Working Examples:

Here's something I wrote in more codey format to refresh my memory on how it all plays out with handling errors etc:

http://jsfiddle.net/nalberg/v95tekz2/

nawlbergs
  • 2,820
  • 1
  • 18
  • 11
17

Just for completion, here is a code example indicating the differences:

success \ error:

$http.get('/someURL')
.success(function(data, status, header, config) {
    // success handler
})
.error(function(data, status, header, config) {
    // error handler
});

then:

$http.get('/someURL')
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
})
.then(function(response) {
    // success handler
}, function(response) {
    // error handler
}).
MichaelLo
  • 1,289
  • 1
  • 14
  • 26
  • great!, do you have an example where the concatenation can be useful ? – geoom May 22 '14 at 07:06
  • 4
    The idea is that the "then" approach is more useful, since you can more easy write asynchronous operations one after the other. – MichaelLo May 22 '14 at 07:18
3

Official Notice: success and error have been deprecated, please use the standard then method instead.

Deprecation Notice: The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

link: https://code.angularjs.org/1.5.7/docs/api/ng/service/$http

screenshot: view the screenshot

Hugo
  • 1,814
  • 1
  • 15
  • 23
MagicBoy
  • 51
  • 1
  • 3