Wie kann ich eine JavaScript-Seite erstellen, die die Internetgeschwindigkeit des Benutzers erkennt und auf der Seite anzeigt? So etwas wie "Ihre Internetgeschwindigkeit ist ?? / ?? Kb / s ” .
Wie kann ich eine JavaScript-Seite erstellen, die die Internetgeschwindigkeit des Benutzers erkennt und auf der Seite anzeigt? So etwas wie "Ihre Internetgeschwindigkeit ist ?? / ?? Kb / s ” .
Antworten:
Es ist bis zu einem gewissen Grad möglich, aber nicht wirklich genau. Die Idee ist, ein Bild mit einer bekannten Dateigröße zu laden und dann in seinem onload
Ereignis zu messen, wie viel Zeit vergangen ist, bis dieses Ereignis ausgelöst wurde, und diese Zeit in die Bilddateigröße zu teilen.
Ein Beispiel finden Sie hier: Berechnen Sie die Geschwindigkeit mit Javascript
Testfall unter Anwendung des dort vorgeschlagenen Fixes:
//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>
Ein schneller Vergleich mit dem "echten" Geschwindigkeitstestdienst ergab einen kleinen Unterschied von 0,12 Mbit / s bei Verwendung des Gesamtbilds.
Um die Integrität des Tests sicherzustellen, können Sie den Code mit aktivierter Drosselung des Chrome Dev-Tools ausführen und dann prüfen, ob das Ergebnis der Einschränkung entspricht. (Gutschrift geht an user284130 :))
Wichtige Dinge zu beachten:
Das verwendete Bild sollte ordnungsgemäß optimiert und komprimiert werden. Wenn dies nicht der Fall ist, zeigt die Standardkomprimierung bei Verbindungen durch den Webserver möglicherweise eine höhere Geschwindigkeit als sie tatsächlich ist. Eine andere Option ist die Verwendung eines nicht komprimierbaren Dateiformats, z. B. jpg. (Danke an Rauli Rajande für diesen Hinweis und Fluxine für die Erinnerung an mich )
Der oben beschriebene Cache-Buster-Mechanismus funktioniert möglicherweise nicht mit einigen CDN-Servern, die so konfiguriert werden können, dass Abfragezeichenfolgenparameter ignoriert werden, wodurch die Cache-Steuerungsheader für das Image selbst besser festgelegt werden. (Dank orcaman für dieses heraus zeigen ) )
Nun, dies ist 2017, also haben Sie jetzt die Netzwerkinformations-API (allerdings mit einer eingeschränkten Unterstützung für alle Browser ab sofort), um Informationen zur geschätzten Downlink-Geschwindigkeit zu erhalten:
navigator.connection.downlink
Dies ist eine effektive Bandbreitenschätzung in Mbit / s. Der Browser nimmt diese Schätzung anhand des kürzlich beobachteten Durchsatzes der Anwendungsschicht über kürzlich aktive Verbindungen vor. Der größte Vorteil dieses Ansatzes besteht natürlich darin, dass Sie keine Inhalte nur zur Berechnung der Bandbreite / Geschwindigkeit herunterladen müssen.
Sie können sich dieses und einige andere verwandte Attribute hier ansehen
Aufgrund der eingeschränkten Unterstützung und der unterschiedlichen Implementierungen zwischen den Browsern (Stand November 2017) würde ich dringend empfehlen, dies im Detail zu lesen
Wie ich in dieser anderen Antwort hier auf StackOverflow skizziere , können Sie dies tun, indem Sie den Download von Dateien verschiedener Größen zeitlich festlegen (klein anfangen, hochfahren, wenn die Verbindung dies zuzulassen scheint), durch Cache-Header sicherstellen, dass die Datei wirklich ist vom Remote-Server gelesen und nicht aus dem Cache abgerufen werden. Dies erfordert nicht unbedingt, dass Sie einen eigenen Server haben (die Dateien könnten von S3 oder ähnlichem stammen), aber Sie benötigen einen Ort, an dem Sie die Dateien abrufen können, um die Verbindungsgeschwindigkeit zu testen.
Allerdings sind Bandbreitentests zu einem bestimmten Zeitpunkt notorisch unzuverlässig, da sie von anderen Elementen beeinflusst werden, die in anderen Fenstern heruntergeladen werden, von der Geschwindigkeit Ihres Servers, von Links auf dem Weg usw. usw. Sie können sich jedoch eine ungefähre Vorstellung machen mit dieser Art von Technik.
iframe
senden, fragen Sie das iframe
oder ein Cookie zum Ausfüllen ab. Wenn Sie ein XMLHttpRequest
Objekt verwenden, um den Beitrag zu verfassen, erfolgt ein Rückruf zur Fertigstellung.
Ich brauchte einen schnellen Weg, um festzustellen, ob die Benutzerverbindungsgeschwindigkeit schnell genug war, um einige Funktionen auf einer Site, an der ich arbeite, zu aktivieren / deaktivieren. Ich habe dieses kleine Skript erstellt, das die durchschnittliche Zeit zum Herunterladen eines einzelnen (kleinen) Bildes a berechnet In meinen Tests funktioniert es ziemlich genau. Ich kann beispielsweise klar zwischen 3G oder Wi-Fi unterscheiden. Vielleicht kann jemand eine elegantere Version oder sogar ein jQuery-Plugin erstellen.
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);
}
}
Der Bildtrick ist cool, aber in meinen Tests wurde er vor einigen Ajax-Aufrufen geladen, die ich abschließen wollte.
Die richtige Lösung für 2017 ist die Verwendung eines Arbeitnehmers ( http://caniuse.com/#feat=webworkers ).
Der Arbeiter wird aussehen wie:
/**
* 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
);
};
Die js-Datei, die den Worker aufruft:
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 aus einem Plone-Paket, das ich geschrieben habe:
Es ist besser, Bilder zum Testen der Geschwindigkeit zu verwenden. Wenn Sie sich jedoch mit Zip-Dateien befassen müssen, funktioniert der folgende Code.
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();
Dies funktioniert nicht sehr gut mit Dateien <10 MB. Sie müssen aggregierte Ergebnisse bei mehreren Downloadversuchen ausführen.
Ich brauchte etwas Ähnliches, also schrieb ich https://github.com/beradrian/jsbandwidth . Dies ist eine Neufassung von https://code.google.com/p/jsbandwidth/ .
Die Idee ist, zwei Anrufe über Ajax zu tätigen, einen zum Herunterladen und einen zum Hochladen über POST.
Es sollte mit beiden jQuery.ajax
oder Angular funktionieren $http
.
Dank der Antwort von Punit S können Sie zum Erkennen einer dynamischen Änderung der Verbindungsgeschwindigkeit den folgenden Code verwenden:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}