0

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?

4

1 回答 1

1

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:

  • it overshadows your original (first) success_cb, so it’s not accessible anymore
  • it instead assigns the event argument of the readystatechange event to success_cb which is an object

“<a href="https://stackoverflow.com/q/5373278/4642212">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");
于 2018-01-15T18:27:31.010 回答