Can someone explain what's going on in this javascript code?

Red Squirrel

No Lifer
May 24, 2003
71,332
14,092
126
www.anyf.ca
I'm mostly a newbie when it comes to JS I just google how to do stuff as I need to. I got this code to work based on googling, but I'm just trying to figure out exactly whta's going on, because the order in which it executes is odd and I just want to make sure I add in the proper checks and error handling but I need to understand it better first.


Code:
function RetrieveAlarms()
{
	const Http = new XMLHttpRequest();
	const url="index.php?mod=getalms";
	
	console.log("RA");

	var xhr = new XMLHttpRequest();
	SetMsg("Updating...");

	xhr.open("GET", url, true);
	

	xhr.onprogress = function () 
	{
	   console.log("IP");
	   SetMsg("Updating......");
	};

	xhr.onload = function () 
	{
	   console.log("load");
	    
	   ProcessAlarms(xhr.responseText);	    
	    
	   SetMsg("Last Updated: " + FormatDate(1234)); 
	};

	xhr.send(null);

	
	console.log("RA end");
}


The part I don't quite understand is how those onprogress and onload parts work, and what does the =function() part do?

I understand that this is basically non blocking sockets, but just trying to figure out how it's executing and in what order. Are they spawning different threads?

Basically the console output for one run (this runs in a loop) is as follows :

Code:
RA
RA end
IP
Load

The fact that IP and Load show AFTER RA End seems to indicate this is running in some kind of thread. Is that what is happening?

Essentially I need to understand this better so I can add in the proper checks to make sure if there are network delays the loop won't try to execute twice when it's already in progress.
 

yottabit

Golden Member
Jun 5, 2008
1,672
874
146
Not a Js pro either but XMLHttpRequest is an "async" function. Js natively supports async execution which can make things tricky to wrap your head around.

XMLHttpRequest is very old and the "vanilla" Js way. Nowadays I would recommend some library like Fetch API or Axios for HTTP requests

The .open or .onprogress or .onload are (I may not have the terminology completely right here) basically binding to events associated with with the request. So you initially call open, and it's unknown how long this will take. The various events then fire off when they are ready.

The = function() { ...} is basically just declaring a new function to execute on the fly with no return value and the body {....}. In modern Js way you may see shorthand arrow function like .open = () => {...} which does the same thing

It's equivalent to if you said:

xhr.onload = myFunction()

and then had a myFunction() { stuff } declared somewhere else in your code. But these on the fly function declarations are more compact and useful when you don't expect to reuse the function anywhere else.

Fetch and Axios both support promises (again another newer Js feature) which IMO make dealing with async a lot easier and more logical

I can highly recommend Brad Traversy's tutorials on YouTube if you're interested in learning more about this stuff (if you can deal with the Boston accent). Mosh also has some good videos on HTTP REST / CRUD and Js
 

Red Squirrel

No Lifer
May 24, 2003
71,332
14,092
126
www.anyf.ca
Oh ok so those functions() are basically sub functions that are part of the main one, and they run as a separate thread after the main one is finished?
 

yottabit

Golden Member
Jun 5, 2008
1,672
874
146
Js is single threaded. It's just that certain commands like the XML Http request execute by default in a "non-blocking" or asynchronous way. So it's not typical 'top down' execution order like you'd expect with synchronous functions. Web api requests and other IO heavy operations are best handled event based/async like this.

Think of the request as having a life cycle. It is initiated, and then the request .onprogress will get called (fired off as an event) once any meaningful progress has been made in the request. No guarantee of when or how long that will take since it's waiting on some other server. You wouldn't want to block the thread that entire time waiting on a response


If you need to have stuff execute after an async operation is complete that's where promises come in handy.

You can define functions inside other functions and they will just be limited in their scope
 

mxnerd

Diamond Member
Jul 6, 2007
6,799
1,103
126
Not familiar with Javascript either, but the concept should be similar. The functions in your code (.onload, .onprogress) only define what they will do when some events happen, it's not executed immediately or by the sequence in the order they appear in the code.

Event driven coding is very different from traditional procedural coding. Clicking a button, open/close a window, moving a mouse, etc are all events. For a GUI program you have to define functions to respond to all those events when they happen. Of course it's not limited to GUI programs, like your code here, however.

Grouping event handler functions together (probably at the end or beginning of the code) makes code cleaner.

The following article gives a very good example. (Too long, didn't read through)

Some said it's better to setup event handler before send() request
==

XMLHttpRequest Living Standard
 
Last edited:

Red Squirrel

No Lifer
May 24, 2003
71,332
14,092
126
www.anyf.ca
The order of how it gets executed is what was confusing me the most, I still don't QUITE get it but that video did help mostly. I basically added some sleeps on the php side so I can make the network part take a long time, and that let me visualize things a bit better and I added the proper code to handle a situation where it takes longer than the cycle delay. Basically I wanted to make sure I don't end up with a situation that the network is slow and it tries to poll when a poll is still not done. So I have that fixed now.
 

purbeast0

No Lifer
Sep 13, 2001
53,765
6,646
126
Check out the docs here - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#event_handlers

The onload and onprogress are events that happen with xhr objects. You need to define the callback functions to execute when those events occur in the xhr object. If you don't declare them, nothing will happen when those 2 events are fired. They are basically just variables that are on the xhr object.

The = function() thing you are talking about is how you declare those callback functions. Those functions are not called when they are declared in the code above. It's just setting the variable to the functions. It would literally be the same thing as setting them to a string or a number or an object. In this case it's setting the variable to a function. But if you did that, when those events happened you probably would get some kind of error just stating they aren't functions.

In your example above, after you set xhr.onprogress to the function, if you added xhr.onprogress() right after setting it to the function, THEN the function would immediately be called and you would see the IP output happen at that time. I think what you are getting caught up on is you are expecting those = function() methods to be called when they are being set to the variables, but they aren't being called they are just being set to the variables and called later on when the event occurs.

I am not too familiar with the low level xhr object since I typically do javascript in frameworks, but I'm guessing nothing actually happens at all with that xhr object until the send method is called. Based on the docs, nothing will happen at all with the xhr object in your example until that send method is called.

Once it's called, it then initiates that GET request. While doing this, the onprogress callback function is called so you see the text from it. Then once the request has completed, you get the onload callback function called and it's done with the request.
 

Red Squirrel

No Lifer
May 24, 2003
71,332
14,092
126
www.anyf.ca
Oh I think I get it now, so "function()" just just declaring a function "on the fly" inside the function. Then I can assign the entire function (not what it returns, but the function itself) to the variable.

So these are basically special variables that hold the actual function and then calls it at a given time (such as when the page loads etc).

The code above is also not perfect and I need to refine it as I also found that if the http server becomes unavailable then it basically gets stuck so I do need to add the proper handling for that. At least I understand more what's going on now so the rest is just the thing of reading on the more specificss of XMLHttpRequest and what other options/flags it has. The concept of callback functions and the concept of declaring them that way was kind of foreign to me so it was kind of a double whammy there trying to figure out what's happening.
 

purbeast0

No Lifer
Sep 13, 2001
53,765
6,646
126
Oh I think I get it now, so "function()" just just declaring a function "on the fly" inside the function. Then I can assign the entire function (not what it returns, but the function itself) to the variable.

So these are basically special variables that hold the actual function and then calls it at a given time (such as when the page loads etc).

The code above is also not perfect and I need to refine it as I also found that if the http server becomes unavailable then it basically gets stuck so I do need to add the proper handling for that. At least I understand more what's going on now so the rest is just the thing of reading on the more specificss of XMLHttpRequest and what other options/flags it has. The concept of callback functions and the concept of declaring them that way was kind of foreign to me so it was kind of a double whammy there trying to figure out what's happening.
Yep it sounds like you are starting to get it. Callbacks and the event handlers are a big part of javascript in general. Since there is a lot of asyncronous concepts in javascript too, there are concepts about how to handle that and the main one is a promise. In the newer syntax there is also this concept of async/await keywords that will make the code a lot more sequential to read.

I'm not sure how familiar you are with the google dev tools but press F12 in Chrome and you will open them. Then you can go into the console and you can type javascript stuff in there.

To kind of "get" what the functions being set on the fly to a variable, you can just do it in the console.

Type something like this.

JavaScript:
// 1.
var a = function(output) {
    console.log('output is %o', output);
}

// 2.
a

// 3.
a('hello world');

You will see that typing 1 does nothing, as in no function is executed or anything like that.

Then if you type 2, it just shows you what a is actually defined as, which is the function.

Then if you type 3, it actually executes the function and you get the output of the function.
 
Last edited:
  • Like
Reactions: mxnerd

Red Squirrel

No Lifer
May 24, 2003
71,332
14,092
126
www.anyf.ca
I don't use Chrome but I it looks like Firefox has a similar console, been using it for other stuff, did not realize I could type in it. Will be a good way to play around with stuff.
 

purbeast0

No Lifer
Sep 13, 2001
53,765
6,646
126
Yeah Firefox has the same type of developer tools but not quite as nice of an overall package. The console though should generally be the same thing though.