If there is ever a moment when you need your internet connection to work, there is a very good chance it is at that very moment your internet connection will fail. This is one of those universally accepted truths...I think. Anyway, building an app or a site whose functionality relies on an internet connection being present is tricky. You can't always guarantee that an internet connection will be available when your app requires it, and this is especially true on mobile devices when your internet connectivity might be flaky.
To avoid situations where something you create misbehaves because an internet connection isn't available, you need a way to detect whether an internet connection exists. The best part is that it isn't very hard to do.
Take a look at the following example:
Click on the Check connection! text. If you have an active internet connection, you will see a dialog telling you that a connection exists:
If you don't have an internet connection (something you can temporarily simulate by unplugging your network cable or turning off your wireless), you will see a dialog that says that an internet connection does not exist:
This crazy-awesome functionality is made possible using a little bit of JavaScript and a simple XMLHttpRequest technique. In this article, you will learn all about it.
Onwards!
The way we check if an internet connection exists pretty simple. There is some code that attempts to access a file that exists on the internet. If we can access that file, this means an internet connection exists:
If we can't access that file, this means an internet connection doesn't exist or something like a firewall or Nicholas Cage is preventing your app from connecting to the internet.
The code for all of what I just described looks as follows:
function doesConnectionExist() { var xhr = new XMLHttpRequest(); var file = "https://i.imgur.com/7ofBNix.png"; var randomNum = Math.round(Math.random() * 10000); xhr.open('HEAD', file + "?rand=" + randomNum, true); xhr.send(); xhr.addEventListener("readystatechange", processRequest, false); function processRequest(e) { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 304) { alert("connection exists!"); } else { alert("connection doesn't exist!"); } } } }
The doesConnectionExist function mimics what our example earlier does. It displays a dialog box indicating whether an internet connection exists or whether it does not exist. To use this code in your own site or app, the only thing you need to do is change the URL specified for the file variable:
var file = "http://www.yoursite.com/somefile.png";
Change the URL to point to any file that you know exists - probably on your own server. That's all there is to it. To see a full working version of this code, check out the source for the example you saw earlier from the following location.
In the previous section, you saw the code that makes all of this work. You also received a very simple explanation as to what the code does. In this section, let's look through each line of our code in detail and get the real explanation...starting at the top:
var xhr = new XMLHttpRequest();
The first thing we do is create the xhr variable and initialize it to a new XMLHttpRequest object. This object contains all of the properties and methods you need for sending or getting data from across the internet without requiring you to refresh your page.
The next three lines are related, so let's look at them together:
var file = "http://www.yoursite.com/somefile.png"; var randomNum = Math.round(Math.random() * 10000); xhr.open('HEAD', file + "?rand=" + randomNum, false);
The file and randomNum variables help you to construct a URL that points to a known file on the internet. You see these variables being used when we call open on our xhr object:
var file = "http://www.yoursite.com/somefile.png"; var randomNum = Math.round(Math.random() * 10000); xhr.open('HEAD', file + "?rand=" + randomNum, false);
The open method is pretty interesting, so let's look at it in more detail.
The open method allows us to construct a request. Think of this is formally defining the parameters you want in order to send your request off to the internet. The open method (in this variation) takes three arguments:
Our HTTP method is going to be HEAD. There are several HTTP methods available that you can specify, but we want to use a method that simply checks on a file without actually downloading it. The HEAD method fits that requirement.
The URL we specify is the path to the file that we want to check on. This URL is a combination of the file and randomNum variables that you saw earlier. Then end result is a string that might look as follows:
https://i.imgur.com/7ofBNix.png?rand=6544
The random number tagged on as part of the URL is there to prevent a cached result from being returned.
The last argument we specify is whether we want this request to be done in the background asynchronously or whether we want this to block all other code from executing and run synchronously. Whether you specify true (asynchronous) or false (synchronous) depends entirely on your app, but you probably just want to keep it at true. Besides providing for a better user experience where your page won't look frozen until a response is returned, some browsers like Chrome complain if you try to make requests synchronously.
So far, all we've done is create our XMLHttpRequest object and constructed our HTTP request. Things really start moving with the next line of code:
xhr.send();
In this line, we call the send method on our xhr object. This is important for one reason: when the send method executes, the HTTP request you constructed earlier in open is actually transmitted. What happens next is handled by the following lines of code:
xhr.addEventListener("readystatechange", processRequest, false); function processRequest(e) { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 304) { alert("connection exists!"); } else { alert("connection doesn't exist!"); } } }
In the first line, we listen to the readystatechange event that our XMLHttpRequest object fires at the various stages of sending and receiving a request:
xhr.addEventListener("readystatechange", processRequest, false);
The event handler that gets called when the readystatechange event is overheard is processRequest:
function processRequest(e) { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 304) { alert("connection exists!"); } else { alert("connection doesn't exist!"); } } }
There are two checks we make here to determine the state of our request.
The first check is to see what the value of our xhr object's readyState property is:
function processRequest(e) { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 304) { alert("connection exists!"); } else { alert("connection doesn't exist!"); } } }
The value we care about is 4, and that translates to our request having been completed. If you are curious to learn more about the readyState property and what the other values are, check out the Making HTTP Requests in JavaScript tutorial.
A request successfully being made isn't the same as having an internet connection that exists and can access the file we are checking for. That is where the next set of checks come in:
function processRequest(e) { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 304) { alert("connection exists!"); } else { alert("connection doesn't exist!"); } } }
Do determine if our internet connection exists, we need to inspect the HTTP status code (xhr.status) that gets returned. Looking at the various status codes goes well beyond the scope of this article, but as long as your status code falls within 200 and 303, you are in good shape and this entire function returns a true.
If your status code goes outside of that range, nobody really knows what is going on. To be safe, our code returns a false to indicate that the connection doesn't exist. It is very likely be that the file you specified as part of your request doesn't exist and needs to be altered. It could be that something else is preventing your connection from succeeding. If you see false being returned consistently, that is a sign that you need to troubleshoot your connection.
After writing this article, several people asked me why I don't use the navigator.onLine property to check whether a connection exists or not. After all, this property's sole reason for existing is to tell you...whether a connection exists or not. It seems like the obvious choice, right? Well, not quite! Here is why I don't like to use it for what we are trying to do.
What we are doing is checking if we have an internet connection. The reason we are doing this is to actually connect to the internet and do something with some remote data. Simply checking if we have a valid connection isn't adequate. I could be connected to a local network and not have access to the broader internet. I could be in a virtual machine with a virtual network adapter that always shows an active connection...even if such a connection doesn't actually exist. You may have a firewall that causes problems. There are many cases where your browser will falsely report a connection exists, but the navigator.onLine property will return true.
By making a web request like this article describes, there is no ambiguity on whether your page can connect to the internet. That's why I prefer the XHR approach as opposed to the navigator.onLine property.
More and more of your sites and apps store state in a remote location. Having an internet connection at all times when using your phone or computer or whatever is no longer a luxury for many parts of the world. It is a necessity. Despite that, we (and your users) always manage to get ourselves into situations where an internet connection might not always exist. I'm looking at you Mammoth Caves.
For those moments when your site or app doesn't have an internet connection that it desperately relies on, this code provides you with a basic solution for how to start dealing with it.
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
:: Copyright KIRUPA 2024 //--