0

I have a web app that needs to check if the web browser is connected to the internet when the function below is called.

function ping(){
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            // Typical action to be performed when the document is ready:
            console.log("response: " + xhttp.responseText);
        }
    };
    xhttp.open("GET", "http://www.google.com", true);
    xhttp.send();
}

Below are the function results from the google chrome console. It somewhat works...

When connected to the internet:

Failed to load https://www.google.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

When no internet connection:

GET https://www.google.com/ 0 ()

So, if I could differentiate between the errors, there would be my function, but I also have a feeling that this is a completely weird way of doing this.

Is there a better/simpler way of checking for an internet connection?

Diomoid
  • 101
  • 10
  • Possible duplicate of [Show error page when no internet (html)](https://stackoverflow.com/questions/49165958/show-error-page-when-no-internet-html) – Nisarg Shah Aug 23 '18 at 07:12
  • 3
    Possible duplicate of [Detect the Internet connection is offline?](https://stackoverflow.com/questions/189430/detect-the-internet-connection-is-offline) – t.niese Aug 23 '18 at 07:12
  • Javascript has an api to detect if there is internet: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/Online_and_offline_events – Jerodev Aug 23 '18 at 07:12
  • [Check if Internet Connection Exists with Javascript?](https://stackoverflow.com/questions/2384167/check-if-internet-connection-exists-with-javascript) – t.niese Aug 23 '18 at 07:13
  • 1
    ask for an image resource instead of using AJAX and you won't be subject to the same CORS restrictions that generate the error in your first quoted text. – Alnitak Aug 23 '18 at 07:25
  • What are the HTTP status codes returned? – minitauros Aug 23 '18 at 07:32

2 Answers2

1

Update

Run the script, Give a try by disconnecting your internet.

window.addEventListener('load', function() {
  var status = document.getElementById("status");
  var log = document.getElementById("log");

  function updateOnlineStatus(event) {
    var condition = navigator.onLine ? "online" : "offline";

    status.className = condition;
    status.innerHTML = condition.toUpperCase();

    log.insertAdjacentHTML("beforeend", "Event: " + event.type + "; Status: " + condition);
  }

  window.addEventListener('online',  updateOnlineStatus);
  window.addEventListener('offline', updateOnlineStatus);
});
#status {
  position: fixed;
  width: 100%;
  font: bold 1em sans-serif;
  color: #FFF;
  padding: 0.5em;
}

#log {
  padding: 2.5em 0.5em 0.5em;
  font: 1em sans-serif;
}

.online {
  background: green;
}

.offline {
  background: red;
}
<div id="status"></div>
<div id="log"></div>
<p>This is a test, Try to disconnect your internet</p>

if(window.navigator.onLine)
  alert('Internet connected')
 else
  alert('internet is not connected')

window.navigator.onLine supported in major browsers now

window.navigator.onLine

Returns the online status of the browser. The property returns a boolean value, with true meaning online and false meaning offline. The property sends updates whenever the browser's ability to connect to the network changes. The update occurs when the user follows links or when a script requests a remote page. For example, the property should return false when users click links soon after they lose internet connection. Reference MDN Navigator.onLine

Satyam Pathak
  • 6,612
  • 3
  • 25
  • 52
  • I would personally not use this answer, given that the article mentioned states "Therefore, if you really want to determine the online status of the browser, you should develop additional means for checking.", meaning that `window.navigator.onLine` is not a reliable way to check for a REAL internet connection. Just go with the original error codes returned. – minitauros Aug 23 '18 at 07:23
  • https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/Online_and_offline_events this might be more explanatory. – Satyam Pathak Aug 23 '18 at 07:27
  • Thank you for elaborating, but what do you think about the first mentioned article stating "So while you can assume that the browser is offline when it returns a false value, you cannot assume that a true value necessarily means that the browser can access the internet. You could be getting false positives..."? – minitauros Aug 23 '18 at 07:29
  • But yes, AJAX can be more reliable but we here trying to be simpler. A proper validation will always be preferred – Satyam Pathak Aug 23 '18 at 07:29
  • I just updated answer with one more snippet i found on MDN, explains the requirements very well. – Satyam Pathak Aug 23 '18 at 07:38
  • 1
    Problem is that if you disconnect from the internet but you keep open a connection to your LAN, or even to an online adapter that does not actually have a connection, your browser will think you are online, but you will still be unable to load the resource you want to load. However, it is better than nothing. Thanks for updating the answer! – minitauros Aug 23 '18 at 07:51
  • This is very nice, thanks for your answer! I need another way of checking for a valid connection though, since if my modem is not connected to the internet (as @minitauros) mentioned, it will still show online. My modem is flaky and sometimes does not provide an internet connection, so that is why I tried to do a simple query to google. Do you know of a simple way to expand upon this? – Diomoid Aug 29 '18 at 00:34
  • I am doing some research after your question, will get back with update to this question. – Satyam Pathak Aug 29 '18 at 07:47
1

The navigator.onLine solution was part of the way there, but it would not give correct results if a computer was connected to a wifi router (that itself was not connected to the internet).

I discovered that CORS was the problem with my approach, and thanks to the people in the comments, I discovered a better way that used an image resource (like @Alnitak said). This answer was helpful in finding out how to handle the image loading and error callbacks.

Here is some simple code to show how I did it.

See the Pen InternetConnection by Daniel (@Diomoid) on CodePen.

HTML

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>InternetConnection</title>
        <script src="InternetConnection.js" type="text/javascript"></script>
    </head>
    <body onload="initialize();">
        <h1 id="status"></h1>
    </body>
</html>

JS

var internetAccess = true;

// Goes to Google and tries to get an image, changes a flag, then calls to update view
function checkInternet(){
    var img = new Image();
    img.onload = function(){
        internetAccess = true;
        updateView();
    };
    img.onerror = function(){
        internetAccess = false;
        updateView();
    };

    // The browser will cache images (and you'll always get a successful 'onload') unless you request a 'dummmy' query ('?dummy=UNIQUE_NUMBERS') so that every image is unique.
    img.src = 'https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png'+"?dummy="+new Date().getTime();
}

function updateView(){
    var isOnline = navigator.onLine && internetAccess;

    if(isOnline){
        console.log("Connected!");
        document.body.bgColor = 'darkgreen';
        document.getElementById("status").innerHTML = "CONNECTED :)";

        // Retest connection to ensure is truly connected... I commented this out since I do not really want to constantly check in my case (I just register a click listener so that I don't have hundreds of requests of small images over an hour if I leave the webpage running).
        // checkSpawner();
    }else{
        console.log("NOT connected");
        document.body.bgColor = 'yellow';
        document.getElementById("status").innerHTML = "NOT CONNECTED :(";

        // Retest connection until it succeeds
        checkSpawner();
    }
}

// Check internet connection every 5 seconds
function checkSpawner(){
    console.log("checking for internet...");
    setTimeout(checkInternet, 5000);
}

// Setup listeners for when the connection is disrupted
function initialize(){
    window.addEventListener("online", checkInternet);
    window.addEventListener("offline", checkInternet);
    checkInternet();
}
Diomoid
  • 101
  • 10