Leo Jiang
Leo Jiang

Reputation: 26085

How do I stop error propagation in JQuery's $.Deferred()?

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?

Upvotes: 3

Views: 1234

Answers (1)

Roamer-1888
Roamer-1888

Reputation: 19288

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.
});

Upvotes: 2

Related Questions