'Promise function working fine in Safari but not in Chrome
RESOLVED. Working code appended to post.
Hope someone can shed some light.
I have a small function to determine network speed using various methods. Link: https://www.hyperspaces.co.uk/hhgdev/nst.html
In safari the function works entirely as expected however, in Chrome, I get the following error from the console:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'toFixed') at networkSpeed (nst.html:76:36)
For the line
document.getElementById("Score").innerHTML = "Network Speed: " + ns.toFixed(2) + " Mbps";
The Code is as follows:
function getNetworkSpeed(url) // test the network connection and return network speed in MBps
{
return new Promise ((resolve, reject) =>
{
getCount = (url = bigImg) ? 10 : 50;
var networkSpeedScore = 0; // create the networkSpeedScore local variable
var fSize = 0;
var connection = window.navigator.connection || window.navigator.mozConnection || null; // is the navigator.connection API supported?
if (connection === null) // if navigator.connection is not supported
{
fSize = -1
xhr = new XMLHttpRequest(); // create a new XMLHttp request
xhr.open("HEAD", url, true); // use "HEAD" instead of "GET" to get only the header
xhr.onreadystatechange = function() // when the request state changes
{
if (this.readyState == this.DONE) // and if the request is complete
{
fSize = (parseInt(xhr.getResponseHeader("Content-Length"))); // get the content length of the image file specified in the 'url' variable in BYTES
}
};
xhr.send(); // start the XMLHttp request
var networkImages = new Array(); // create an array to hold the 1k images
var lastImageLoaded = 0; // track the last image in the array to sucessfully complete loading
var networkStartTime = (new Date()).getTime(); // get the start time for the speed test
for (i=0; i<getCount; i++) // loop to load the image 100 times
{
networkImages[i] = new Image(); // add new image object ot array
networkImages[i].src = url + "?n=" + Math.random(); // load the image from its source (adding a random number query to the string to force reload of the same file)
}
var interval = setInterval(function () // call this function at 50 millisecond intervals
{
for (i=0; i<getCount; i++) // loop through the images in the loading queue
{
var networkCurrentTime = (new Date()).getTime(); // get the current time in the process
if (networkImages[i].complete == true) // if the image in the array has finished loading
{
lastImageLoaded = i+1; // keep track of how many images have completed loading
}
}
if (lastImageLoaded == getCount || networkCurrentTime - networkStartTime >= 1000) // if all images have loaded or one second has passed
{
clearInterval(interval) // stop the function from checking which images have loaded
if (lastImageLoaded == 0 || fSize == -1) // if no images have loaded
{
networkSpeedScore = 0; // to avoid negative scores and divide by zero errors - sets speed as 1kpbs
resolve(networkSpeedScore); // return the network speed - good result is over 1.5 (M bits per sec)
}
else
{
var totalTime = ((networkCurrentTime - networkStartTime) / 1000); // total time taken in seconds
networkSpeedScore = ((lastImageLoaded * fSize)/ totalTime) / 125000; // network speed in M bits per second
}
resolve(networkSpeedScore); // return the network speed - good result is over 1.5 (M bits per sec)
}
}, 50);
}
else
{
networkSpeedScore = connection.bandwidth; // get the network bandwith from the navigator.connection API
resolve(networkSpeedScore);
}
});
}
async function networkSpeed()
{
ns = await getNetworkSpeed(bigImg); // A big image should be around 100k in size for the first attempt
if (ns = 0) // But, sometimes a large image does not work on poor or unreliable networks
{ // Using a smaller image (~1K) will give a better result in this case
ns = await getNetworkSpeed(smallImg); // Run the function again with a smaller file
}
console.log("Network Speed: "+ns.toFixed(2)+" Mbps");
document.getElementById("Score").innerHTML = "Network Speed: " + ns.toFixed(2) + " Mbps";
}
bigImg = "sysimages/coverpage.jpg"; // any image on your site that is approx 100k in size
smallImg = "sysimages/blue_square.png"; // any image on your site that is approx 1k in size
networkSpeed();
<!DOCTYPE html>
<html>
<body>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 30pt" id="Score">FETCHING NETWORK STATISTICS</p>
</body>
</html>
<!DOCTYPE html>
<html>
<body>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 30pt" id="Score">FETCHING NETWORK STATISTICS</p>
<script>
function getNetworkSpeed(url) // test the network connection and return network speed in MBps
{
return new Promise ((resolve, reject) =>
{
getCount = (url = bigImg) ? 10 : 50;
var networkSpeedScore = 0; // create the networkSpeedScore local variable
var fSize = -1
xhr = new XMLHttpRequest(); // create a new XMLHttp request
xhr.open("HEAD", url, true); // use "HEAD" instead of "GET" to get only the header
xhr.onreadystatechange = function() // when the request state changes
{
if (this.readyState == this.DONE) // and if the request is complete
{
fSize = (parseInt(xhr.getResponseHeader("Content-Length"))); // get the content length of the image file specified in the 'url' variable in BYTES
}
};
xhr.send(); // start the XMLHttp request
var networkImages = new Array(); // create an array to hold the 1k images
var lastImageLoaded = 0; // track the last image in the array to sucessfully complete loading
var networkStartTime = (new Date()).getTime(); // get the start time for the speed test
for (i=0; i<getCount; i++) // loop to load the image 100 times
{
networkImages[i] = new Image(); // add new image object ot array
networkImages[i].src = url + "?n=" + Math.random(); // load the image from its source (adding a random number query to the string to force reload of the same file)
}
var interval = setInterval(function () // call this function at 50 millisecond intervals
{
for (i=0; i<getCount; i++) // loop through the images in the loading queue
{
var networkCurrentTime = (new Date()).getTime(); // get the current time in the process
if (networkImages[i].complete == true) // if the image in the array has finished loading
{
lastImageLoaded = i+1; // keep track of how many images have completed loading
}
}
if (lastImageLoaded == getCount || networkCurrentTime - networkStartTime >= 1000) // if all images have loaded or one second has passed
{
clearInterval(interval) // stop the function from checking which images have loaded
if (lastImageLoaded == 0 || fSize == -1) // if no images have loaded
{
networkSpeedScore = 0; // to avoid negative scores and divide by zero errors - sets speed as 1kpbs
}
else
{
var totalTime = ((networkCurrentTime - networkStartTime) / 1000); // total time taken in seconds
networkSpeedScore = ((lastImageLoaded * fSize)/ totalTime) / 125000; // network speed in M bits per second
}
resolve(networkSpeedScore); // return the network speed - good result is over 1.5 (M bits per sec)
}
}, 50);
});
}
async function networkSpeed()
{
ns = await getNetworkSpeed(bigImg); // A big image should be around 100k in size for the first attempt
if (ns == 0) // But, sometimes a large image does not work on poor or unreliable networks
{ // Using a smaller image (~1K) will give a better result in this case
ns = await getNetworkSpeed(smallImg); // Run the function again with a smaller file
}
document.getElementById("Score").innerHTML = "Network Speed: " + ns.toFixed(2) + " Mbps";
}
bigImg = "sysimages/coverpage.jpg"; // any image on your site that is approx 100k in size
smallImg = "sysimages/blue_square.png"; // any image on your site that is approx 1k in size
networkSpeed();
</script>
</body>
</html>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
