Come posso creare una pagina JavaScript che rileverà la velocità di Internet dell'utente e la mostrerà sulla pagina? Qualcosa come "la tua velocità di internet è ?? / ?? Kb / s " .
Come posso creare una pagina JavaScript che rileverà la velocità di Internet dell'utente e la mostrerà sulla pagina? Qualcosa come "la tua velocità di internet è ?? / ?? Kb / s " .
Risposte:
È possibile in una certa misura, ma non sarà molto preciso, l'idea è caricare l'immagine con una dimensione del file nota, quindi nel suo onload
evento misurare quanto tempo è trascorso prima che l'evento sia stato attivato e dividere questa volta per la dimensione del file di immagine.
Qui puoi trovare un esempio: calcola la velocità usando JavaScript
Caso di prova applicando la correzione suggerita lì:
//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>
Il rapido confronto con il servizio di test della velocità "reale" ha mostrato una piccola differenza di 0,12 Mbps quando si utilizza un'immagine di grandi dimensioni.
Per garantire l'integrità del test, puoi eseguire il codice con la limitazione dello strumento di sviluppo di Chrome abilitata e quindi vedere se il risultato corrisponde alla limitazione. (il credito va all'utente284130 :))
Cose importanti da tenere a mente:
L'immagine utilizzata deve essere adeguatamente ottimizzata e compressa. In caso contrario, la compressione predefinita per le connessioni da parte del server Web potrebbe mostrare una velocità maggiore di quella attuale. Un'altra opzione sta usando un formato di file non comprimibile, ad esempio jpg. (grazie Rauli Rajande per averlo segnalato e Fluxine per avermelo ricordato )
Il meccanismo di busting della cache descritto sopra potrebbe non funzionare con alcuni server CDN, che possono essere configurati per ignorare i parametri della stringa di query, quindi impostare meglio le intestazioni di controllo della cache sull'immagine stessa. (grazie orcaman per averlo segnalato ) )
Bene, questo è il 2017, quindi ora hai l'API delle informazioni di rete (anche se con un supporto limitato tra i browser a partire da ora) per ottenere una sorta di stima della velocità di downlink:
navigator.connection.downlink
Questa è una stima della larghezza di banda effettiva in Mbits al secondo. Il browser effettua questa stima dal throughput del livello applicazione osservato di recente attraverso connessioni attive di recente. Inutile dire che il più grande vantaggio di questo approccio è che non è necessario scaricare alcun contenuto solo per il calcolo della larghezza di banda / velocità.
Puoi vedere questo e un paio di altri attributi correlati qui
A causa del supporto limitato e delle diverse implementazioni tra i browser (a partire da novembre 2017), consigliamo vivamente di leggere questo in dettaglio
Come ho delineato in questa altra risposta qui su StackOverflow , puoi farlo tempificando il download di file di varie dimensioni (inizia piccolo, accelera se la connessione sembra consentirlo), assicurandoti attraverso le intestazioni della cache e tale che il file sia davvero viene letto dal server remoto e non viene recuperato dalla cache. Questo non richiede necessariamente che tu abbia un tuo server (i file potrebbero provenire da S3 o simili), ma avrai bisogno di un posto da cui ottenere i file per testare la velocità di connessione.
Detto questo, i test della larghezza di banda point-in-time sono notoriamente inaffidabili, poiché sono influenzati da altri elementi scaricati in altre finestre, dalla velocità del server, dai collegamenti lungo il percorso, ecc. Ecc. Ma puoi avere un'idea approssimativa usando questo tipo di tecnica.
iframe
, ad esempio, esegui il polling del iframe
cookie o di un cookie per il completamento. Se usi un XMLHttpRequest
oggetto per scrivere il post, c'è un callback per il completamento.
Avevo bisogno di un modo rapido per determinare se la velocità di connessione dell'utente era abbastanza veloce da abilitare / disabilitare alcune funzionalità in un sito su cui sto lavorando, ho realizzato questo piccolo script che calcola la media del tempo necessario per scaricare una (piccola) immagine a molte volte, sta funzionando abbastanza accuratamente nei miei test, essendo in grado di distinguere chiaramente tra 3G o Wi-Fi, ad esempio, forse qualcuno può creare una versione più elegante o persino 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);
}
}
Il trucco dell'immagine è bello ma nei miei test si stava caricando prima che alcune chiamate ajax volessi essere complete.
La soluzione corretta nel 2017 è quella di utilizzare un lavoratore ( http://caniuse.com/#feat=webworkers ).
Il lavoratore sarà simile a:
/**
* 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
);
};
Il file js che invocherà il lavoratore:
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);
}
};
Codice preso da un pacchetto Plone che ho scritto:
È meglio usare le immagini per testare la velocità. Ma se hai a che fare con i file zip, il codice qui sotto funziona.
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();
Questo non funzionerà molto bene con file <10 MB. Dovrai eseguire risultati aggregati su più tentativi di download.
Avevo bisogno di qualcosa di simile, quindi ho scritto https://github.com/beradrian/jsbandwidth . Questa è una riscrittura di https://code.google.com/p/jsbandwidth/ .
L'idea è di effettuare due chiamate tramite Ajax, una da scaricare e l'altra da caricare tramite POST.
Dovrebbe funzionare con entrambi jQuery.ajax
o angolari $http
.
grazie alla risposta Punit S, per rilevare la variazione dinamica della velocità di connessione, è possibile utilizzare il seguente codice:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}