In this article, we will cover 3 things:
How to detect your JS application (it can be SPA, PWA, Electron, or plain JS) is having a troubled connection (slow, offline), when it gets back online and how to re-download the data without a page refresh (in case it hasn't got enough time to finish while online).
Creating a simple JS application that downloads and displays a picture, where we would cover all the cases from a previous step.
Learning how to throttle the Internet connection in Chrome, and test the application we created.
Step 1.
To detect if the application got offline, or back online, is quite simple:
window.addEventListener("offline", () => {
console.log("I am offline.");
});
window.addEventListener("online", () => {
console.log("I am back online.");
});
If you are building a Chrome extension that requires the Internet connection, for example to upload a file to Google Drive, you can leverage following:
if (!navigator.onLine) {
return false;
}
// Upload the file...
To detect if the application is loading for too long, can be done by creating a timer and giving it a time, after which we assume the connection is slow, if not loaded yet. After the application is loaded, we reset the timer. Here's an example code:
// Our simple App
const App = async (onstart, onload) => {
onstart();
// Loading...
// The application is now loaded
onload();
}
let isSlow;
let loaded;
App(
() => {
isSlow = setTimeout(() => {
console.log("Thing are getting slow...");
}, 10000); // 10 seconds
},
() => {
clearTimeout(isSlow);
loaded = true;
console.log("Loaded.");
});
The logic by which we decide if the application is loading for too long, depends on our app.
Now, we can proceed to the next step.
Step 2.
We will now create a simple app, that will load a random picture from https://picsum.photos. If the Internet connection will get slow, offline, or back online, we will display a particular message:
The app will look like this:
The message will be displayed in the top center when needed. To make the loading of an image visually nicer, it will have a pulsing effect to it.
Let's start by creating index.html
:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App</title>
<link rel="stylesheet" href="app.css">
</head>
<body>
<div id="slow" class="message">Slow Internet Connection.</div>
<div id="offline" class="message">No Internet Connection.</div>
<div id="online" class="message">Back Online.</div>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>
Continue by creating app.css
:
body {
margin: 0;
padding: 4em;
font-family: Arial, Helvetica, sans-serif;
}
@keyframes pulse {
0% { background-color: #f1f1f1; }
100% { background-color: silver; }
}
img {
width: 640px;
height: 480px;
}
img.loading {
animation: pulse 1s ease-out alternate infinite;
}
.message {
position: fixed;
left: 50%;
top: 0;
font-size: 2em;
font-weight: bold;
padding: 1.5em;
transform: translate(-50%, -100%);
transition: transform .25s;
}
#slow {
background: #FF9800;
color: white;
}
#offline {
background: #E91E63;
color: white;
}
#online {
background: #4CAF50;
color: white;
}
body.slow #slow,
body.offline #offline,
body.online #online {
transform: translate(-50%, 0);
}
Messages (or Alerts) have different color each, and are off the screen when not needed. When required, the message slides in from the top center.
And finally, create app.js
:
// Simple App that loads a picture.
const App = (onstart, onload) => {
onstart();
const h1 = document.createElement("h1");
h1.innerText = "App";
const img = document.createElement("img");
img.src = "https://picsum.photos/640/480";
img.className = "loading";
img.onload = () => {
img.className = "";
onload();
};
const app = document.getElementById("app");
app.innerHTML = "";
app.append(h1);
app.append(img);
}
let isSlow;
let loaded;
const loadApp = () => {
App(
() => {
loaded = false;
isSlow = setTimeout(() => {
// Show "Slow Internet Connection." message.
document.body.className = "slow";
console.debug("slow");
}, 1500); // Intentionally a low number for testing. Try some different values here, or play with different Internet Throttling setting.
},
() => {
loaded = true;
clearTimeout(isSlow);
setTimeout(() => { document.body.className = ""; }, 1000); // Hide message after 1s.
console.debug("loaded");
});
};
// We are "offline".
window.addEventListener("offline", () => {
// Show "No Internet Connection." message.
document.body.className = "offline";
});
// When we back "online".
window.addEventListener("online", () => {
// Show "Back online" message.
document.body.className = "online";
console.debug("online");
// Hide message after 1s.
setTimeout(() => { document.body.className = ""; }, 1000);
// There was not enough time to load the App. Do it again.
if (!loaded) {
console.debug("Reconnecting...");
loadApp();
}
});
window.addEventListener("DOMContentLoaded", loadApp);
This simple App will load a picture and display it. While the picture is loading, it will have a .loading
class added, to show the pulse effect. After the image is loaded, the .loading
class will be removed, and the timer will be stopped. If the loading took longer than we specified, Slow Internet Connection.
message will be shown.
If the Internet is off, No Internet Connection.
message will be displayed, and once back online, Back Online.
message will be displayed.
In case the picture wasn't loaded before we got offline, it will be loaded once again we are back online.
Step 3.
Time to test our App under different network conditions. Open Chrome -> DevTools -> Network, look for Throttling section and click Add....
Define 2 new Throttling profiles as seen below:
A random picture we are about to display, can range anywhere from 20KB to 80KB in size, that means, in Very slow profile that would take about 5 seconds to load, in Incredibly slow profile about 30 seconds. We basically adjust the speed to the size of content, to get a good testing.
Now, open index.html
with the DevTools open (to have Throttling applied), keep refreshing the page with different initial Throttling setting (Online, Offline, Very slow or Incredibly slow), and try changing the profile while the page is loading (from Offline to Online; from Incredibly slow to Offline to Online; etc.).
It can look like this:
That's it. I hope you enjoyed the article and had fun!
And. Thank you for reading! 🙂
Top comments (3)
Thank you Zoe, I haven't thought about that yet but sounds like a nice idea.
Great read! Thanks for sharing!
Thanks that's really help! I live in country where connection is so f bad. This really like Gem!