it is a common pattern that we cascade across a list of sources of data with the first success breaking the chain like this:
var data = getData1();
if (!data) data = getData2();
if (!data) data = getData3();
et cetera. if the getDataN() functions are asynchronous, however, it leads us to 'callback hell':
var data;
getData1(function() {
getData2(function () {
getData3(function () { alert('not found'); })
})
});
where the implementations may look something like:
function getData1(callback) {
$.ajax({
url: '/my/url/1/',
success: function(ret) { data = ret },
error: callback
});
}
...with promises I would expect to write something like this:
$.when(getData1())
.then(function (x) { data = x; })
.fail(function () { return getData2(); })
.then(function (x) { data = x; })
.fail(function () { return getData3(); })
.then(function (x) { data = x; });
where the second .then
actually refers to the return value of the first .fail
, which is itself a promise, and which I understood was chained in as the input to the succeeding chain step.
clearly I'm wrong but what is the correct way to write this?
In most promise libs, you could chain
.fail()
or.catch()
as in @mido22's answer, but jQuery's.fail()
doesn't "handle" an error as such. It is guaranteed always to pass on the input promise (with unaltered state), which would not allow the required "break" of the cascade if/when success happens.The only jQuery Promise method that can return a promise with a different state (or different value/reason) is
.then()
.Therefore you could write a chain which continues on error by specifying the next step as a then's error handler at each stage.
But in practice, you might more typically create an array of functions or data objects which are invoked in turn with the help of Array method
.reduce()
.For example :
Or, as is probably a better solution here :