-1

I have the following code in javascript:

var max = 0;                                             //<---- HERE

var request = new XMLHttpRequest();
request.open('GET', 'HERE_GOES_API_ADDRESS', true);
request.onload = function (max) {                         //<---- HERE

  // Begin accessing JSON data here
  var data = JSON.parse(this.response);
  if (request.status >= 200 && request.status < 400) {
    data.forEach(LoginLog => {

      window['max'] = LoginLog.id;                        //<---- HERE


    });
  } else {
    const errorMessage = document.createElement('marquee');
    errorMessage.textContent = `Gah, it's not working!`;
    app.appendChild(errorMessage);
  }

}

request.send();

console.log(max);                                      // <---- HERE Gives 0

The expected value of max after the loop is 2. However, I am always getting 0.

why is the window not working? isn't supposed to be used when updating a global variable?

P.S: I have to update the max variable globally. console.log(max) was written only for testing purposes.

yasserkabbout
  • 201
  • 1
  • 14
  • **Timing** is the issue here, not scope! – deceze Dec 23 '18 at 21:39
  • @deceze That question is not what is being asked about here. The issue is the re-declaration of a global and the incorrect expectation that the global is being passed to the callback. – Scott Marcus Dec 23 '18 at 21:39
  • @Scott It very much is, the concept of asynchronous execution is lost on OP. – deceze Dec 23 '18 at 21:41
  • @deceze That is certainly an issue, but the the one that the OP is asking about. The dup. that you linked to doesn't address the OPs mistake here. See my answer. – Scott Marcus Dec 23 '18 at 21:41

1 Answers1

0

Event callback functions are always automatically passed the event that they are handling as their first argument, so when you write:

request.onload = function (max) { 

You are not actually passing max to the function, you are declaring a function argument to receive the first parameter that is passed to the function when it is invoked. When that happens it will be the load event of the request object and the event is evaluating to a number of 0. If you want to access a global in your callback, just reference it directly as max and don't both setting up an argument for the callback.

EDIT:

In addition to the issue above, the fact that you have console.log(max); sitting outside of the async. callback means that it will run before the async. operation is complete. Move that statement so that it is inside of the callback.

var max = 0; 

var request = new XMLHttpRequest();
request.open('GET', 'HERE_GOES_API_ADDRESS', true);
request.onload = function () {    // No argument needed

  // Begin accessing JSON data here
  var data = JSON.parse(this.response);
  if (request.status >= 200 && request.status < 400) {
    data.forEach(LoginLog => {

      max = LoginLog.id;  // Just use the global
      console.log(max);   // Access the async result in the callback
    });
  } else {
    const errorMessage = document.createElement('marquee');
    errorMessage.textContent = `Gah, it's not working!`;
    app.appendChild(errorMessage);
  }

}

request.send();
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Yes, OP is declaring a useless parameter `max` which shadows the outer variable, but that parameter is never used and hence doesn't do anything good or bad. – deceze Dec 23 '18 at 21:44
  • @deceze I get your point and it's related, but the question is about accessing globals and the OP is attempting it incorrectly, so the dup link isn't going to help. I've edited my answer to address the related async. issue. – Scott Marcus Dec 23 '18 at 21:46
  • Yeah. But the problem is that I have to use the max value after the request.send() call.. not within it.. That's why I am trying to modify the global variable.. I added the console.log(max) just for testing purposes. – yasserkabbout Dec 23 '18 at 21:47
  • @yasser You can't, period. Work *with* asynchronous execution, not against it. – deceze Dec 23 '18 at 21:48
  • @deceze What can be a work around? the problem is that i have to pass this max variable to another API call... – yasserkabbout Dec 23 '18 at 21:57
  • 1
    @yasserkabbout You would simply do that from within the async. `load` callback because that's when you have the data you need. – Scott Marcus Dec 23 '18 at 21:58
  • @ScottMarcus do you mean calling an async inside an async? – yasserkabbout Dec 23 '18 at 22:03
  • @yasserkabbout No, I mean you can't know when the async. result will be done, so you have to put any code that needs to run after the async. is finished in the async. callback function. It could be another async. or not, that's doesn't really matter. – Scott Marcus Dec 24 '18 at 15:29