0

If i have

promise = userService.updateUser($stateParams.userId, req);

promise.then(
    function(user) {
        logger.logSuccess('Updated user');
        $scope.resetForm();
        WizardHandler.wizard().goTo(0);
        return user;
    }, 
    function(error) {
        logger.logError('Ups an error has occurred');
        console.error('error updating user: ' + error);
    }
); 

promise.then(function(user) {
    _.each(uploader.getNotUploadedItems(), function(item) {
        return item.formData.push({
            id: user.id
        });
    });
});

Then if the updateUser fails the log will be shown and then second then will not be executed however if i have

promise = userService.updateUser($stateParams.userId, req).then(
    function(user) {
        logger.logSuccess('Updated user');
        $scope.resetForm();
        WizardHandler.wizard().goTo(0);
        return user;
    }, 
    function(error) {
        logger.logError('Ups an error has occurred');
        console.error('error updating user: ' + error);
    }
); 

promise.then(function(user) {
    _.each(uploader.getNotUploadedItems(), function(item) {
        return item.formData.push({
            id: user.id
        });
    });
});

The second then will be executed

I can't figure out why, i mean isn't this just regular chaining ?

Constantin Groß
  • 10,719
  • 4
  • 24
  • 50
forcewill
  • 1,637
  • 2
  • 16
  • 31

1 Answers1

2

if the updateUser fails the log will be shown and then second then will not be executed

Yes, because you're branching the promise chains:

              success: - logSuccessAndResetForm()
               |       - makeNewFormData()
updateUser() --+
  promise      |
              error    - logError()

but when using regular chaining the second chain will be executed

Yes, of course. Your error handler handles the error and the promise is fulfilled with the return value.

              success: - logSuccessAndResetForm()           success: - makeNewFormData()
               |                               \             |
updateUser() --+                                >- promise --+
               |                               /             |
              error    - logError()           ´             error:   (nothing)

See also this answer for prettier control flow diagrams of similar code.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Footnote for anyone trying to follow this through: what Bergi says is correct for js native promises and most mainstream promise libs. But **be alert to jQuery promises**, which behave differently. In jQuery, a .then's error handler marks the downstream promise as "handled" *only if* it explicitly returns a rejected promise. The natural behaviour is to propagate the error state. So neither version of the code in the question will fire the second then's success handler. Please note also that the folks at jQuery are likely to normalize this behaviour at some point in the future. – Roamer-1888 Mar 23 '15 at 17:08
  • @Roamer-1888: [That's not their only problem](http://stackoverflow.com/a/23744774/1048572), but really I don't want to need to link that post on every promise-tagged question. jQuery deferreds are no proper promises, point :-) – Bergi Mar 23 '15 at 17:21
  • Bergi, I agree, you can't offer the "jQuery proviso" every time. But your diagrams make this answer very clear and compelling - it's likely to be read by many people. – Roamer-1888 Mar 23 '15 at 17:25
  • To be fair they're fixing it, in fact they merged the fix to their master branch just a few days ago and in 3.0 which will come shortly the issue is fixed as well as the timing issues :) – Benjamin Gruenbaum Mar 24 '15 at 07:51
  • @Bergi .then() returns another promise then and not the original promise ? is that it, i guess i need to read more on promises to fully grasp them – forcewill Mar 25 '15 at 09:49
  • @forcewill: Yes, it does. [That's the point of promises](http://stackoverflow.com/a/22562045/1048572) actually :-) – Bergi Mar 25 '15 at 12:20