A slow internet connection is a mind-boggling experience in areas with slow internet connectivity. Sometimes you may have a highly performant app but your users’ internet connection hinders them from enjoying experience of your website/web app. As such, it is important to build resilient applications that can quickly detect slow internet connection and notify the users promptly.
In JavaScript, a slow connection is a promise, or network request, that doesn't settle (resolve or reject) at a specific time and instead stays in the pending state indefinitely.
Remember there is a difference between a slow network (a promise that doesn't settle for a while) and a no network (a promise that settles with rejection), which typically returns error 404.
You can detect ‘no network’ using javascript offline and online events before making a request. Read this online/offline events article here
Javascript is a single threaded and non-blocking language.
Before I show you how to detect slow network on your website/web app, lets understand some JavaScript concepts; Javascript is a single threaded and non-blocking language.
It is single threaded as it only processes one item at a time running a script line by line from top to bottom.
It is a non-blocking language in that when a Javascript interpreter encounters a lengthy process, it doesn't wait for it to finish but instead it delegates a callback function that will handle when the process completes then continues to the next line.
Async/await functions were introduced in JavaScript Ecmascript 2017 (ES2017), allowing Javascript interpreter to use the keyword await inside a function to wait for an asynchronous operation to finish before moving on to the next line. In other words, async/await functions violate Javascript's non-blocking nature inside a function.
Lets now implement single threaded and non-blocking nature of JS to detect slow network and here is how we will do it:
- Determine the time to deem an internet connection as slow. (for our test we will use 500ms and throttle the network).Normally it could 30 seconds to a minute.
- Declare an async/await data fetching function .
- Declare a
payload
variable as null and later assign data from network request. - Set up a setTimeout method inside of async/await function just before
await
keyword, the method takes a callback function that will check if a promise has settled at a given time by checking if payload is still null or received data from REST API.
Callback function is a function given to another function as an argument.it is a powerful feature in JavaScript and work horse of node JS. Read More the difference between callback functions and high order functions
Our HTML code
<button id="network-btn" style="padding:0.5rem;
background:rebeccapurple;
color:white;
border-radius:8px;
outline:none;
width: 150px;
margin:5rem;"> Get Posts <button>
Our Javascript code
const networkBtn = document.getElementById("network-btn");
let timeout = 500; // let assume its too slow at 500ms
let payload = null;
let clearTimer=null /* to clear our setTimeout, initialised as null */
const checkNetwork = () => {
/* if after half a second payload variable is still null,
it means we are still awaiting the promise to settle */
if (payload === null) {
alert("Your internet connection is slow");
}
};
async function getPosts() {
let url = `https://jsonplaceholder.typicode.com/posts/`;
/* we clear any timeout*/
if(clearTimer !== null) clearTimeout(clearTimer)
try {
/*the callback in setTimeout will be executed regardless of the await keyword below it*/
clearTimer=setTimeout(checkNetwork, timeout);
const response = await fetch(url);
payload = await response.json();
return payload;
} catch (error) {
console.error(error.message);
}
}
const handleNetwork = () => {
getPosts();
};
networkBtn.addEventListener("click", handleNetwork);
We have assummed that half a second (500ms) is a slow connection for our testing purposes,Open devtools newtork tab ctrl+shift+I
to throttle network to slow 3G, when you run that code you should see an alert saying _ your internet connection is slow _.
We can cancel the request and ask the user if they wish to retry the request, abort request with AbortController
then call getPosts
function again. Read how to cancel an AJAX request with AbortController
const networkBtn = document.getElementById("network-btn");
let timeout = 500; // let assume its too slow at 500ms
let payload = null;
let abortController=null
let recalled = 0; /* we want to only retry calling the function once to avoid infinite function calls*/
const checkNetwork = () => {
/* if after half a second payload variable is still null,
it means we are still awaiting the promise to settle */
if (payload === null) {
if (confirm("Your internet connection is slow, do you wish to retry?")) {
abortController.abort();
if (recalled <= 1) getPosts();
recalled++;
};
}
};
async function getPosts() {
abortController = new AbortController();
let signal = abortController.signal;
let url = `https://jsonplaceholder.typicode.com/posts/`;
try {
setTimeout(checkNetwork, timeout);
const response = await fetch(url, { signal });
payload = await response.json();
return payload;
} catch (error) {
console.error(error.message);
}
}
const handleNetwork = () => {
getPosts();
};
networkBtn.addEventListener("click", handleNetwork);
To summarise, async/await gave javaScript functions a blocking aspect that developers can use to their advantage by pausing everything while they wait for an action to finish while on the other end manipulating with callbacks.
Resources:
MDN Async function
A Beginner’s Guide to JavaScript async/await, with Examples
Top comments (0)