web-dev-qa-db-fra.com

Comment détecter la vitesse d'Internet en JavaScript?

Comment créer une page JavaScript qui détecte la vitesse de l’internet et la montre Quelque chose comme "votre vitesse Internet est ??/?? Kb/s ”.

176
Sharon Haim Pour

C'est possible dans une certaine mesure, mais cela ne sera pas vraiment précis. L'idée est de charger l'image avec une taille de fichier connue, puis, dans son événement onload, de mesurer le temps écoulé jusqu'à ce que cet événement soit déclenché et de diviser cette fois la taille du fichier d'image.

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éelle" a montré une petite différence de 0,12 Mbps lors de l'utilisation d'une image globale.

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 va à user284130 :))

Points importants à garder à l'esprit:

  1. L'image utilisée doit être correctement optimisée et compressée. Si ce n'est pas le cas, la compression par défaut des connexions du serveur Web peut indiquer une vitesse supérieure à celle réelle. Une autre option consiste à utiliser un format de fichier incompressible, par exemple. jpg. (merci Rauli Rajande pour pour l'avoir signalé et Fluxine pour me le rappeler)

  2. Le mécanisme de busage de 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 paramétrage des en-têtes de contrôle de cache sur l'image elle-même. (merci à orcaman pour le signaler ))

249
Shadow Wizard

Eh bien, nous sommes en 2017 et vous disposez maintenant d'une API d'informations réseau (avec un support limité pour les navigateurs actuels) pour obtenir une sorte d'informations de vitesse estimation sur la 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 couche d'application récemment observé sur les connexions récemment actives. Il va sans dire que le principal avantage de cette approche est que vous ne devez télécharger aucun contenu uniquement pour le calcul de la bande passante/vitesse.

Vous pouvez consulter ceci et quelques autres attributs associés ici _

En raison de son support limité et de ses différentes implémentations sur les navigateurs (à compter de novembre 2017), il est vivement recommandé de lire this en détail

40
Punit S

Comme je l'explique 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, accélérez si la connexion semble le permettre), en veillant sur les en-têtes de cache et tels que le fichier est en cours de lecture sur le serveur distant et n'est pas récupéré à partir 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 emplacement pour obtenir les fichiers afin de tester la vitesse de connexion.

Cela dit, les tests de bande passante à un point dans le temps sont notoirement peu fiables, car ils sont impactés par le téléchargement d’autres éléments téléchargés dans d’autres fenêtres, la vitesse de votre serveur, les liens en route, etc., mais vous pouvez vous faire une idée générale. en utilisant ce genre de technique.

19
T.J. Crowder

J'avais besoin d'un moyen rapide de déterminer si la vitesse de connexion de l'utilisateur était suffisamment rapide pour activer/désactiver certaines fonctionnalités d'un site sur lequel je travaille. J'ai créé ce petit script qui calcule la durée moyenne du téléchargement d'une seule (petite) image a nombre de fois, cela fonctionne assez bien dans mes tests, étant capable de distinguer clairement entre 3G ou 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);
  }
}

11
dmm79

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 <10Mo. Vous devrez exécuter des résultats agrégés sur plusieurs tentatives de téléchargement.

5
Akshar

Le truc de l’image est cool, mais lors de mes tests, il se chargeait avant quelques appels ajax, je voulais être complet.

La solution appropriée en 2017 consiste à 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 appellera le travailleur:

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 tiré d'un paquet Plone que j'ai écrit:

5
alepisa

J'avais besoin de quelque chose de similaire, alors j'ai é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. 

Cela devrait fonctionner avec jQuery.ajax ou angulaire $http.

3
Adrian Ber

Vous pouvez déterminer le temps de chargement de la page. Essayez d’utiliser le script suivant pour mesurer le temps nécessaire au chargement complet d’une page:

<html>
<head>
<script type="text/javascript">

var start = new Date().getTime();
function onLoad() {
  var now = new Date().getTime();
  var latency = now - start;
  alert("page loading time: " + latency);
 }

</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>

Voir la page 3WC sur la synchronisation de la navigation: 
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html

1
mintedsky

grâce à Punit S answer, pour détecter le changement dynamique 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');
}
0
Mehdi Maghrooni