0

I'm trying to pull in some JSON data via AJAX for a Greasemonkey script.

Here's what I have:

var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
    var xmlresult = JSON.parse(this.response);
    // this works
    console.log(xmlresult);
  }
};
xmlhttp.open("GET", "https://raw.githubusercontent.com/mledoze/countries/master/countries.json", true);
xmlhttp.send();

// this doesn't work
console.log(xmlresult);

For some reason, xmlresult is always empty. If I dump out the response in the console directly, there's clearly data in the response, but if I try to do anything with it outside of my if block, it doesn't exist.

CXL
  • 1,094
  • 2
  • 15
  • 38
  • 2
    `[...], but if I try to do anything with it outside of my if block[...]` where outside of the `if` block do you try to access it? If it is outside of the callback then it won't be populated because the request is async. Show a full minimal example the illustrates where it is empty when you try to access it. – t.niese Sep 12 '17 at 14:55
  • like you can see I added a console.log to your snippet and it works (shows the json) – gaetanoM Sep 12 '17 at 15:03
  • I was trying to access the result outside that block of code, after `xmlhttp.send()` without any luck. – CXL Sep 12 '17 at 15:22
  • This is not an AJAX issue. The question lacks a basic understanding of scope. – PJ Brunet Oct 07 '17 at 09:57

1 Answers1

-1

That is because xmlresult is a local variable in the onreadystatechange listener function and it's value won't be kept for outside use. You should do:

var xmlresult;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
    xmlresult = JSON.parse(this.response);
  }
};
xmlhttp.open("GET", "https://raw.githubusercontent.com/mledoze/countries/master/countries.json", true);
xmlhttp.send();
Catalin Iancu
  • 722
  • 5
  • 18
  • Yes, it needs to be global or at least to be outside of the scope of the listener function, depending on where it's value is needed. – Catalin Iancu Sep 12 '17 at 14:59
  • 1
    Doesn't matter if it's global, when the method is **asynchronous**? – adeneo Sep 12 '17 at 14:59
  • 1
    this is async, your best bet is to pass a callback that fires once the response data is received. or look into promises – Jay Lane Sep 12 '17 at 15:01
  • It does matter if the method is asynchronous, because the `xmlresult` variable will get a value only at a latter time when the async function is complete. Usually, you can isolate the moment by making a function call with what you need to do in the async function body. – Catalin Iancu Sep 12 '17 at 15:01
  • You are missing something. In the original post, the variable IS defined inside the function scope with the `var` keyword, so it won't be visible outside at all. But I have changed that in my answer to show the right way to do it. – Catalin Iancu Sep 12 '17 at 15:08
  • @CatalinIancu - I added a function inside the onreadystatechange IF block passing the parsed JSON result, and that seems to have addressed my problem. Thank you! Also - I tried defining the variable outside the block, but it was still null. – CXL Sep 12 '17 at 15:21