3

I thought fail() would stop error propagation, but that doesn't seem to happen. Here's what I have:

someAsynTask()
  .then(function(){
    1/0;
  })
  .fail(function(){
    console.log('Error handled.');
  })
  .then(function(){
    console.log('test'); // not printed (expected it to print)
  })
  .fail(function(){
    console.log('More errors?'); // printed (nor expecting it to print)
  });

How do I make fail() catch the error to prevent it from propagating down the promise chain?

Leo Jiang
  • 24,497
  • 49
  • 154
  • 284
  • Dividing by 0 isn't throwing any error in JS – Denys Séguret Jun 08 '15 at 07:12
  • 2
    I think this will help you understand what's going on http://stackoverflow.com/questions/23744612/problems-inherent-to-jquery-deferred – oiledCode Jun 08 '15 at 07:15
  • The biggest problem here is that jQuery doesn't handle exceptions as do native/A+ promises. So, fail isn't even called if you have an exception thrown – Denys Séguret Jun 08 '15 at 07:18
  • `fail` doesn't return a new promise at all, it just attaches a callback and returns the original one. There is no "propagation" and no "chain", there is only the old promise that is rejected. You're looking for `.then(null, function(){ console.log("error handled"); })` (but see @elio.ds comment) – Bergi Jun 14 '15 at 21:59
  • or: [Differences between `deferred.then(null,func)` and `deferred.fail(func)` in jQuery?](http://stackoverflow.com/q/30719183/1048572) – Bergi Jun 14 '15 at 22:08

1 Answers1

2

Two things with jQuery, up to 2.x.

  • promises are not "throw safe"
  • presence of a .fail() handler will not cause the downstream promise to be marked as "handled".

Only .then() has "filtering" power but even with .then(), filtering is not automatic.

From 3.0, we are told that jQuery promises will be promises/A+ compliant.

The behaviour of 1.x and 2.x is thoroughly predictable and even likeable, just not the same as A+. The following code should give the behaviour you were expecting :

someAsynTask().then(function(){
    try {
        1/0;
    } catch(e) {
        return $.Deferred().reject(e).promise(); // Returning a rejected promise from a then()'s success handler is the only way to transmogrify success into failure. An uncaught `throw` does not have the same effect in jQuery 1.x and 2.x.
    }
}).then(null, function(){
    var message = 'Error handled';
    console.log(message);
    return $.when(message); //Returning a resolved promise from a then()'s fail handler is the only way to transmogrify failure into success in jQuery 1.x and 2.x.
}).then(function(msg) {
    console.log(msg); // should print 'Error handled' again
}).fail(function() {
    console.log('More errors?'); // should not print. Also, no filtering here. `.fail()` does not possess filtering power.
});
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
  • What do you mean by filtering power? – Leo Jiang Jun 08 '15 at 17:21
  • You will see that in the [jQuery documentation for .then](https://api.jquery.com/deferred.then/) the functions passed as callbacks are called the "doneFilter", "failFilter" and "progressFilter". They are called filters because they have the power to affect the promise that is propagated down the chain. The `.done()`, `.fail()` and `.progress()` methods do not possess this capability. – Roamer-1888 Jun 08 '15 at 18:09