Comment puis-je créer une page JavaScript qui détectera la vitesse Internet de l'utilisateur et l'affichera sur la page? Quelque chose comme "votre vitesse Internet est ?? / ?? Kb / s » .
Comment puis-je créer une page JavaScript qui détectera la vitesse Internet de l'utilisateur et l'affichera sur la page? Quelque chose comme "votre vitesse Internet est ?? / ?? Kb / s » .
Réponses:
Il est possible dans une certaine mesure mais ne sera pas vraiment précis, l'idée est de charger l'image avec une taille de fichier connue, puis de onload
mesurer dans son événement le temps écoulé avant que cet événement ne se déclenche, et de diviser ce temps en taille de fichier image.
Un exemple peut être trouvé ici: Calculer la vitesse en utilisant javascript
Cas de test appliquant le correctif suggéré ici:
//JUST AN EXAMPLE, PLEASE USE YOUR OWN PICTURE!
var imageAddr = "http://www.kenrockwell.com/contax/images/g2/examples/31120037-5mb.jpg";
var downloadSize = 4995374; //bytes
function ShowProgressMessage(msg) {
if (console) {
if (typeof msg == "string") {
console.log(msg);
} else {
for (var i = 0; i < msg.length; i++) {
console.log(msg[i]);
}
}
}
var oProgress = document.getElementById("progress");
if (oProgress) {
var actualHTML = (typeof msg == "string") ? msg : msg.join("<br />");
oProgress.innerHTML = actualHTML;
}
}
function InitiateSpeedDetection() {
ShowProgressMessage("Loading the image, please wait...");
window.setTimeout(MeasureConnectionSpeed, 1);
};
if (window.addEventListener) {
window.addEventListener('load', InitiateSpeedDetection, false);
} else if (window.attachEvent) {
window.attachEvent('onload', InitiateSpeedDetection);
}
function MeasureConnectionSpeed() {
var startTime, endTime;
var download = new Image();
download.onload = function () {
endTime = (new Date()).getTime();
showResults();
}
download.onerror = function (err, msg) {
ShowProgressMessage("Invalid image, or error downloading");
}
startTime = (new Date()).getTime();
var cacheBuster = "?nnn=" + startTime;
download.src = imageAddr + cacheBuster;
function showResults() {
var duration = (endTime - startTime) / 1000;
var bitsLoaded = downloadSize * 8;
var speedBps = (bitsLoaded / duration).toFixed(2);
var speedKbps = (speedBps / 1024).toFixed(2);
var speedMbps = (speedKbps / 1024).toFixed(2);
ShowProgressMessage([
"Your connection speed is:",
speedBps + " bps",
speedKbps + " kbps",
speedMbps + " Mbps"
]);
}
}
<h1 id="progress">JavaScript is turned off, or your browser is realllllly slow</h1>
Une comparaison rapide avec le service de test de vitesse "réel" a montré une petite différence de 0,12 Mbps lors de l'utilisation de la grande image.
Pour garantir l'intégrité du test, vous pouvez exécuter le code avec la limitation de l'outil de développement Chrome activée, puis voir si le résultat correspond à la limitation. (le crédit revient à user284130 :))
Choses importantes à garder à l'esprit:
L'image utilisée doit être correctement optimisée et compressée. Si ce n'est pas le cas, la compression par défaut sur les connexions par le serveur Web peut afficher une vitesse supérieure à ce qu'elle est réellement. Une autre option consiste à utiliser un format de fichier non compressible, par exemple jpg. (merci Rauli Rajande de l'avoir signalé et Fluxine de me l' avoir rappelé )
Le mécanisme de cache cache décrit ci-dessus peut ne pas fonctionner avec certains serveurs CDN, qui peuvent être configurés pour ignorer les paramètres de chaîne de requête, d'où un meilleur réglage des en-têtes de contrôle du cache sur l'image elle-même. (merci orcaman pour avoir signalé ) )
Eh bien, nous sommes en 2017, vous avez donc maintenant l'API d'informations réseau (bien qu'avec une prise en charge limitée sur les navigateurs à partir de maintenant) pour obtenir une sorte d' estimation des informations sur la vitesse de liaison descendante:
navigator.connection.downlink
Il s'agit d'une estimation de la bande passante effective en Mbits par seconde. Le navigateur effectue cette estimation à partir du débit de la couche d'application récemment observé sur les connexions récemment actives. Inutile de dire que le plus grand avantage de cette approche est que vous n'avez pas besoin de télécharger de contenu uniquement pour le calcul de la bande passante / vitesse.
Vous pouvez consulter cela et quelques autres attributs connexes ici
En raison de sa prise en charge limitée et des différentes implémentations entre les navigateurs (en novembre 2017), je recommande fortement de lire ceci en détail
Comme je le souligne dans cette autre réponse ici sur StackOverflow , vous pouvez le faire en chronométrant le téléchargement de fichiers de différentes tailles (commencez petit, augmentez si la connexion semble le permettre), en vous assurant via les en-têtes de cache et que le fichier est vraiment étant lu à partir du serveur distant et non récupéré du cache. Cela ne nécessite pas nécessairement que vous ayez votre propre serveur (les fichiers peuvent provenir de S3 ou similaire), mais vous aurez besoin d'un endroit pour obtenir les fichiers afin de tester la vitesse de connexion.
Cela dit, les tests de bande passante ponctuels sont notoirement peu fiables, étant donné qu'ils sont impactés par d'autres éléments téléchargés dans d'autres fenêtres, la vitesse de votre serveur, les liens en cours de route, etc., etc. Mais vous pouvez avoir une idée approximative en utilisant ce genre de technique.
iframe
, par exemple, vous interrogez le iframe
ou un cookie pour l'achèvement. Si vous utilisez un XMLHttpRequest
objet pour faire le post, il y a un rappel pour terminer.
J'avais besoin d'un moyen rapide pour déterminer si la vitesse de connexion de l'utilisateur était assez rapide pour activer / désactiver certaines fonctionnalités dans un site sur lequel je travaille, j'ai créé ce petit script qui fait la moyenne du temps nécessaire pour télécharger une seule (petite) image a plusieurs fois, cela fonctionne assez précisément dans mes tests, étant capable de distinguer clairement entre la 3G ou le Wi-Fi par exemple, peut-être que quelqu'un peut faire une version plus élégante ou même un plugin jQuery.
var arrTimes = [];
var i = 0; // start
var timesToTest = 5;
var tThreshold = 150; //ms
var testImage = "http://www.google.com/images/phd/px.gif"; // small image in your server
var dummyImage = new Image();
var isConnectedFast = false;
testLatency(function(avg){
isConnectedFast = (avg <= tThreshold);
/** output */
document.body.appendChild(
document.createTextNode("Time: " + (avg.toFixed(2)) + "ms - isConnectedFast? " + isConnectedFast)
);
});
/** test and average time took to download image from server, called recursively timesToTest times */
function testLatency(cb) {
var tStart = new Date().getTime();
if (i<timesToTest-1) {
dummyImage.src = testImage + '?t=' + tStart;
dummyImage.onload = function() {
var tEnd = new Date().getTime();
var tTimeTook = tEnd-tStart;
arrTimes[i] = tTimeTook;
testLatency(cb);
i++;
};
} else {
/** calculate average of array items then callback */
var sum = arrTimes.reduce(function(a, b) { return a + b; });
var avg = sum / arrTimes.length;
cb(avg);
}
}
L'astuce d'image est cool mais dans mes tests, elle se chargeait avant quelques appels ajax, je voulais être complète.
La bonne solution en 2017 est d'utiliser un travailleur ( http://caniuse.com/#feat=webworkers ).
Le travailleur ressemblera à:
/**
* This function performs a synchronous request
* and returns an object contain informations about the download
* time and size
*/
function measure(filename) {
var xhr = new XMLHttpRequest();
var measure = {};
xhr.open("GET", filename + '?' + (new Date()).getTime(), false);
measure.start = (new Date()).getTime();
xhr.send(null);
measure.end = (new Date()).getTime();
measure.len = parseInt(xhr.getResponseHeader('Content-Length') || 0);
measure.delta = measure.end - measure.start;
return measure;
}
/**
* Requires that we pass a base url to the worker
* The worker will measure the download time needed to get
* a ~0KB and a 100KB.
* It will return a string that serializes this informations as
* pipe separated values
*/
onmessage = function(e) {
measure0 = measure(e.data.base_url + '/test/0.bz2');
measure100 = measure(e.data.base_url + '/test/100K.bz2');
postMessage(
measure0.delta + '|' +
measure0.len + '|' +
measure100.delta + '|' +
measure100.len
);
};
Le fichier js qui invoquera le Worker:
var base_url = PORTAL_URL + '/++plone++experimental.bwtools';
if (typeof(Worker) === 'undefined') {
return; // unsupported
}
w = new Worker(base_url + "/scripts/worker.js");
w.postMessage({
base_url: base_url
});
w.onmessage = function(event) {
if (event.data) {
set_cookie(event.data);
}
};
Code extrait d'un package Plone que j'ai écrit:
Il est préférable d'utiliser des images pour tester la vitesse. Mais si vous devez gérer des fichiers zip, le code ci-dessous fonctionne.
var fileURL = "your/url/here/testfile.zip";
var request = new XMLHttpRequest();
var avoidCache = "?avoidcache=" + (new Date()).getTime();;
request.open('GET', fileURL + avoidCache, true);
request.responseType = "application/zip";
var startTime = (new Date()).getTime();
var endTime = startTime;
request.onreadystatechange = function () {
if (request.readyState == 2)
{
//ready state 2 is when the request is sent
startTime = (new Date().getTime());
}
if (request.readyState == 4)
{
endTime = (new Date()).getTime();
var downloadSize = request.responseText.length;
var time = (endTime - startTime) / 1000;
var sizeInBits = downloadSize * 8;
var speed = ((sizeInBits / time) / (1024 * 1024)).toFixed(2);
console.log(downloadSize, time, speed);
}
}
request.send();
Cela ne fonctionnera pas très bien avec des fichiers <10 Mo. Vous devrez exécuter des résultats agrégés sur plusieurs tentatives de téléchargement.
J'avais besoin de quelque chose de similaire, j'ai donc écrit https://github.com/beradrian/jsbandwidth . Il s'agit d'une réécriture de https://code.google.com/p/jsbandwidth/ .
L'idée est de passer deux appels via Ajax, l'un à télécharger et l'autre à télécharger via POST.
Il devrait fonctionner avec les deux jQuery.ajax
ou angulaire $http
.
grâce à la réponse Punit S, pour détecter les changements dynamiques de vitesse de connexion, vous pouvez utiliser le code suivant:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}