2

I'm building a building a website using the Reddit API to display images from Reddit. I'm getting the data via JSON then use it to build the page, using URLs provided as sources for the images.

Some of the URLs that I get don't go to images directly, but instead to image hosting sites (like imgur.com). Usually, adding '.jpg' at the end of the URL takes me to the right image.

So, doing that, I would like to check if the URL + '.jpg' exists before using it.

I tried to build a function to check the url.

function checkUrl(url){
    var request = new XMLHttpRequest;
    request.open('GET', url, true);
    request.send();
    request.onreadystatechange = function(){
        if(request.readyState==4){
            console.log(request.readyState);
            return true;
        }else{
            return false;
        }
    }
};

//Then I use the function to check and append the data to the page
var url = url+'.jpg';
if(checkUrl(url)){
    //work with the data
}else{
    //do nothing
}

Nothing happens to the page, still I get the readyState logged into the console, so the checkUrl() function seems to be returning true.

What I am doing wrong ? I am pretty new to the whole Ajax thing, so some help would very appreciated.

Thank you

Simon Be
  • 199
  • 2
  • 2
  • 9

5 Answers5

3

Your problem is that when request.readyState == 4 this means the request has completed, regardless of what the result of that request was. So even if the URL you request returns a "404 not found", you'll still see the XHR resolving itself to readyState 4.

To address what you're trying to do, I'd recommend checking the status code of the response. For example, using your code:

if(request.status==200){
   return true;
}
joeltine
  • 1,610
  • 17
  • 23
  • I just tried that, but whenever I use request.status, it breaks the whole javascript, and i get this error in the console : Uncaught Error: INVALID_STATE_ERR: DOM Exception 11 – Simon Be Feb 08 '13 at 01:16
  • Edit : That's only in Chrome. The code is still working in Firefox, but it's not appending the data. – Simon Be Feb 08 '13 at 01:29
  • After I wrote this, I also realized what others have said in this thread... due to your AJAX requests asynchronous nature, checkurl will never actually return a true/false value. What you want to do is perform the logic in a "success" case in the if(status==200) statement and the error case in the else. – joeltine Feb 08 '13 at 03:49
3

Why your code won't work:

Your AJAX request is asynchronous, and if(checkUrl(url)){ will return null (false) as the function checkUrl() sends the AJAX request and immediately returns, before the AJAX call has completed.

Change

request.open('GET', url, true);

to

request.open('GET', url, false);

Also, move your request.send() to after the request.onreadystatechange() as now it is a non-async request.

request.onreadystatechange = function(){
    if(request.readyState==4){
        console.log(request.readyState);
        return true;
    }else{
        return false;
    }
}
request.send();

Or, you could simply place your check logic into the onreadystatechange function:

request.onreadystatechange = function(){

    var url = url+'.jpg';
    if(request.readyState==4){
        //work with the data
    }else{
        //do nothing
    }
}
Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
3

I believe your problem is misunderstanding of AJAX; AJAX is basically asynchronous, and that's why the behavior you are describing.
I've used the following to get a simple true/false indication whether a URL is valid, in a synchronous manner:

function isValidURL(url) {
    var encodedURL = encodeURIComponent(url);
    var isValid = false;

    $.ajax({
      url: "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22" + encodedURL + "%22&format=json",
      type: "get",
      async: false,
      dataType: "json",
      success: function(data) {
        isValid = data.query.results != null;
      },
      error: function(){
        isValid = false;
      }
    });

    return isValid;
}

The usage is then trivial:

var isValid = isValidURL("http://www.wix.com");
alert(isValid ? "Valid URL!!!" : "Damn...");

Hope this helps

Ohad
  • 242
  • 3
  • 15
  • I think you need to use `type: "head"` instead of `type: "get"`. GET returns everything where HEAD just returns the headers, which is all you actually need to test a URL. – TheCarver Aug 04 '14 at 21:03
2

The return value of request.reonreadystatechange is not the return value of checkUrl. Try this:

function checkUrl(url){
    var request = new XMLHttpRequest;
    request.open('GET', url, true);
    request.send();
    request.onreadystatechange = function(){
        if(request.readyState==4){
            console.log(request.readyState);
            // perform your data manipulation here
            // don't separate it with the request
        }
    }
};
Lim H.
  • 9,870
  • 9
  • 48
  • 74
1

On Safari, ActiveXObject will work fine, compared to XMLHttpRequest:

function isThere(url)
{
    var req= new AJ(); // XMLHttpRequest object
    try {
        req.open("HEAD", url, false);
        req.send(null);
        //alert(req.status); //un-comment if need alert for status code

        return req.status== 200 ? true : false;
    }
    catch (er) {
        //alert ('ERROR:'); // un-comment if need alert for error
        return false;
    }
}

function AJAX()
{
    var obj;
    if (window.XMLHttpRequest) obj= new XMLHttpRequest();
    else if (window.ActiveXObject)
    {
        try
        {
            obj= new ActiveXObject('MSXML2.XMLHTTP.3.0');
        }
        catch(er)
        {
            try
            {
                obj= new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(er)
            {
                obj= false;
            }
        }
    }
    return obj;
}
MarredCheese
  • 17,541
  • 8
  • 92
  • 91