2

Why is this code not working (when calling the handleRequestStateChange function)?:

function ajaxRequest(){ 
 var xmlObj = new XMLHttpRequest();
 xmlObj.open("GET","1.php",true);
 xmlObj.onreadystatechange = handleRequestStateChange;
 xmlObj.send(null);
}

var handleRequestStateChange = function(){  
    if(xmlObj.readyState == 4 && xmlObj.status==200){
        alert("if loaded");
    }
}

but this one is(without calling the handleRequestStateChange function):

function ajaxRequest(){

 var xmlObj = new XMLHttpRequest();
 xmlObj.open("GET","1.php",true);

 xmlObj.onreadystatechange = function(){
    if(xmlObj.readyState == 4 && xmlObj.status==200){
            alert("if loaded");
    }
 }
 xmlObj.send(null);}
nnnnnn
  • 138,378
  • 23
  • 180
  • 229
denispr00
  • 63
  • 2
  • 4
  • In the first example, at the time you say `xmlObj.onreadystatechange = handleRequestStateChange;`, the variable `handleRequestStateChange;` has no value. It is only assigned a value a few statements later when you declare it to be a function. – Jonathan M May 12 '14 at 22:11
  • 1
    I am not sure @JonathanM is correct, since through variable hoisting/late calling the callback could be defined depending on when you call `ajaxRequest`, but in `handleRequestStateChange` you reference `xmlObj` and even if the request is added correctly, that variable is out of scope and therefore undefined. – lemieuxster May 12 '14 at 22:16

1 Answers1

4

In this particular case, the problem is simply in the scope of the variables, and in this case, ajaxRequest can "see" handleRequestStateChange but handleRequestStateChange cannot "see" xmlObj. In the second example, the anonymous function can see xmlObject because it's "inside" ajaxRequest.

A good place to start is this stackoverflow answer. https://stackoverflow.com/a/500459/1480215

For example, removing the var actually fixes the first code (not that that's a good idea).

function ajaxRequest(){ 
  xmlObj = new XMLHttpRequest(); //suddenly global scope
  xmlObj.open("GET","1.php",true);
  xmlObj.onreadystatechange = handleRequestStateChange;
  xmlObj.send(null);
}

var handleRequestStateChange = function(){  
  if(xmlObj.readyState == 4 && xmlObj.status==200){
    alert("if loaded");
  }
}

The code below would also work

function ajaxRequest(){ 
  var xmlObj = new XMLHttpRequest();
  var handleRequestStateChange = function(){  
    if(xmlObj.readyState == 4 && xmlObj.status==200){
      alert("if loaded");
    }
  }
  xmlObj.open("GET","1.php",true);
  xmlObj.onreadystatechange = handleRequestStateChange;
  xmlObj.send(null);
  //but not if var handleRequestStateChange is here
  //due to https://stackoverflow.com/a/336868/1480215
}

For completeness I'll also include the snippet below which should work

function ajaxRequest(){ 
  var xmlObj = new XMLHttpRequest();

  xmlObj.open("GET","fragments.htm",true);
  xmlObj.onreadystatechange = handleRequestStateChange;
  xmlObj.send(null);

  function handleRequestStateChange(){ //this will work instead of var funcName=function(){}
    if(xmlObj.readyState == 4 && xmlObj.status==200){
      alert("if loaded");
    }
  }    
}

If we are talking about strictly xmlHttpRequest events (or events in general) then it's also possible to use the passed event argument.

function ajaxRequest(){ 
  var xmlObj = new XMLHttpRequest();
  xmlObj.open("GET","1.php",true);
  xmlObj.onreadystatechange = handleRequestStateChange;
  xmlObj.send(null);
}

var handleRequestStateChange=function(event){   //event handlers passes this, generally
  var xmlObj=event.target || event.srcElement   //for compatibility
  //but just having XMLHttpRequest(), is not fully cross-platform anyway
  if(xmlObj.readyState == 4 && xmlObj.status==200){
    alert("if loaded");
  }
}

Moving forward, I think it might be a good idea to use a small existing ajax snippet or library like http://www.openjs.com/scripts/jx/. Maybe even jQuery which also has RPC (including <script>s to include scripts from other domains without COR)

Community
  • 1
  • 1
mfirdaus
  • 4,494
  • 1
  • 22
  • 26