javascriptajaxxmlhttprequestonreadystatechange

Uncaught TypeError when invoking callbacks


I had an error that I have managed to fix on my own. Can someone please explain to me why my code wasn’t working and the mechanics of what caused it.

Code is included below:

var listTables = function (tables) {
  console.log(tables);
}

var ajaxReq = function (success_cb, url) {
  // success_cb can be invoked here without errors
  var http = new XMLHttpRequest();
  http.onreadystatechange = function (success_cb) {
    if (this.readyState == 4 && this.status == 200) {
      success_cb(this); // Uncaught TypeError: success_cb is not a function
    }
  }
  http.open("GET", url, true);
  http.send();
}
ajaxReq(listTables, "http://www.someurl.com");

When I remove the success_cb callback from the onreadystatechange function definition the code works fine. Is this an issue that is related to scope?


Solution

  • The mistake is that you repeated success_cb as a parameter in the inner function:

    var ajaxReq = function (success_cb, url) { // First time success_cb parameter is used: correct.
      var http = new XMLHttpRequest();
      http.onreadystatechange = function (success_cb) { // Second time: wrong!
        // ...
      }
      // ...
    }
    

    This does two unintended things:

    Overshadowing” means, that a variable (or parameter) of the same name is provided that is scoped closer than the previous one.

    So just remove the second usage:

    var listTables = function (tables) {
      console.log(tables);
    }
    
    var ajaxReq = function (success_cb, url) {
      // success_cb can be invoked here without errors
      var http = new XMLHttpRequest();
      http.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
          success_cb(this);
        }
      }
      http.open("GET", url, true);
      http.send();
    }
    ajaxReq(listTables, "http://www.someurl.com");