navy1978
navy1978

Reputation: 1439

Download file from a different url if the others are not available

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

Answers (5)

Anton Kochev
Anton Kochev

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

Neelesh
Neelesh

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

zlumer
zlumer

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

Dogbert
Dogbert

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

Mitya
Mitya

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

Related Questions