Reputation: 1439
I have different urls to different servers but same file, in order to be sure that one of the above servers is alive I would like to try to download from the first, if it fails try with the second and so on....
If there a better way to do it instead of use the one I have in my mind? that is this:
var urls=["http://Url1.com","http://Url2.com","http://Url3.com"]
$.get(ulrs[0]).done(function () {
alert("success");
}).fail(function () {
alert(" First failed!, try with second");
$.get(ulrs[1]).done(function () {
alert("success");
}).fail(function () {
alert("Second failed! Try with third...");
$.get(ulrs[2]).done(function () {
alert("success");
}).fail(function () {
alert("All failed!");
});
});
});
EDIT: I would like to generalize it in order to be used with different arrays with different sizes...
Upvotes: 0
Views: 484
Reputation: 370
Using of recursion is a good approach as has been mentioned at the top of topic.
function loadFirst(query, successHandler, failHandler) {
// Load next if any item in array exists
if (Array.isArray(query) && query.length) {
// Get next item and remove it from query
$.get(query.splice(0, 1))
// First successfull response
.done(function (response) { successHandler(response); })
// Go to the next iteration if request failed
.fail(function() { loadFirst(query); });
} else {
// All requests failed
failHandler();
}
}
Upvotes: 0
Reputation: 736
You can use recursion. Whenever ajax request fail make another ajax call with next url like this : -
var url = ["http://url1.com", "http://url2.com"]
var makeCall = function(url, index){
var xhr = $.ajax(url[index])
.done(function(data) {
console.log("Got the data");
})
.fail(function() {
console.log("Error : trying next url");
makeCall(url, index+1);
});
}
makeCall(url, 0);
Upvotes: 1
Reputation: 7004
Use recursion:
function requestNext(arr, success, error) {
if (!arr.length)
return error();
function onError() {
alert(url + " failed!");
requestNext(arr, success, error);
}
var url = arr.shift();
$.get(url).done(success).fail(onError);
}
var urls = ["http://Url1.com","http://Url2.com","http://Url3.com"];
requestNext(urls, function(){ alert("success"); }, function(){ alert("all failed") });
The urls
array will be mutated after this function completes. If you don't want this to happen, either pass a copy:
requestNext(urls.slice(), function(){ alert("success"); }, function(){ alert("all failed") });
Or use Dogbert's solution, change var url = arr.shift();
to:
var url = arr[0];
arr = arr.slice(1);
Upvotes: 3
Reputation: 222198
You can use a simple recursive function:
function tryGet(urls, done, fail) {
if (urls.length == 0) {
fail();
} else {
$.get(urls[0])
.done(done)
.fail(function() {
tryGet(urls.slice(1), done, fail);
});
}
}
Demo:
tryGet(["http://Url1.com", "http://Url2.com", "http://Url3.com"], function(_, _, resp) {
console.log(resp.status);
}, function() {
console.log("all failed");
});
tryGet(["http://Url1.com", "http://Url2.com", "http://Url3.com", "/"], function(_, _, resp) {
console.log(resp.status);
}, function() {
console.log("all failed");
});
https://jsfiddle.net/Dogbert/t89xn9ej/
Upvotes: 3
Reputation: 34566
Your general approach is pretty much the only available. One way or another, you've got to fire multiple requests, each after the first waiting for the previous to complete before being fired.
What you can do is make your code more readable instead of all that nesting, and make it dynamic so it works with N number of URLs. Something like:
var urls = ['url-1', '/', 'url-2'/* etc */], next_index = 0;
function do_req() {
$.get(urls[next_index]).done(success).error(function() {
next_index++;
if (urls[next_index]) do_req(); else alert('All URLs failed');
});
}
function success() {
alert('Address '+(next_index+1)+' ('+urls[next_index]+') worked!');
}
do_req();
Upvotes: 1