I’m gearing up for an article explaining how Deferred chains move between errback and callback chains, and how to deal with some of the more esoteric issues we all come up with.
For now, an interesting snippet:
// Create a dummy deferred in the error state var d = new dojo.Deferred(); d.errback(new Error("FAIL")); // And start chaining d = d.then( function(response) { console.log("success1 :: " + response); }, function(error) { console.log("error1 :: " + error); }); d = d.then( function(response) { console.log("success2 :: " + response); }, function(error) { console.log("error2 :: " + error); });
Through reading various articles online, I expected that flow would stay in the errback chain, and error2 would fire with the original error as an argument. However, in all versions of Dojo, the above code will result in:
error1 :: Error: FAIL
success2 :: undefined
Unexpected. If we explicitly return the Error that was originally provided to the first errback function, like so:
// Create a dummy deferred in the error state var d = new dojo.Deferred(); d.errback(new Error("FAIL")); // And start chaining d = d.then( function(response) { console.log("success1 :: " + response); }, function(error) { console.log("error1 :: " + error); return error; }); d = d.then( function(response) { console.log("success2 :: " + response); }, function(error) { console.log("error2 :: " + error); });
We get:
error1 :: Error: FAIL
success2 :: Error: FAIL
Some online articles state that returning an Error from a callback or errback function will cause the flow to move into the errback chain. This is actually true only when using traditional addCallback() and addErrback() functions.
So, when using then(), we need to do the following:
// Create a dummy deferred in the error state var d = new dojo.Deferred(); d.errback(new Error("FAIL")); // And start chaining d = d.then( function(response) { console.log("success1 :: " + response); }, function(error) { console.log("error1 :: " + error); throw error; }); d = d.then( function(response) { console.log("success2 :: " + response); }, function(error) { console.log("error2 :: " + error); });
error1 :: Error: FAIL
error2 :: Error: FAIL
This will result in some extra errors in your console log. But it may make things work as you expect.
For more information, and some quite detailed test cases, take a look at the dojo.Deferred tests.