Jak mogę utworzyć stronę JavaScript, która wykryje prędkość Internetu użytkownika i wyświetli go na stronie? Coś w stylu „Twoja prędkość Internetu wynosi ?? / ?? Kb / s ” .
Jak mogę utworzyć stronę JavaScript, która wykryje prędkość Internetu użytkownika i wyświetli go na stronie? Coś w stylu „Twoja prędkość Internetu wynosi ?? / ?? Kb / s ” .
Odpowiedzi:
Jest to w pewnym stopniu możliwe, ale nie będzie naprawdę dokładne, pomysł polega na załadowaniu obrazu o znanym rozmiarze pliku, a następnie w jego onload
zdarzeniu zmierz, ile czasu upłynęło do wyzwolenia tego zdarzenia, i podziel ten czas na rozmiar pliku obrazu.
Przykład można znaleźć tutaj: Oblicz prędkość za pomocą javascript
Przypadek testowy z zastosowaniem sugerowanej tam poprawki:
//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>
Szybkie porównanie z „rzeczywistą” usługą testowania prędkości wykazało niewielką różnicę 0,12 Mb / s przy użyciu dużego obrazu.
Aby zapewnić integralność testu, możesz uruchomić kod z włączonym ograniczeniem narzędzia deweloperskiego Chrome, a następnie sprawdzić, czy wynik odpowiada ograniczeniu. (kredyt trafia do użytkownika 284130 :))
Ważne rzeczy, o których należy pamiętać:
Używany obraz powinien być odpowiednio zoptymalizowany i skompresowany. Jeśli tak nie jest, wówczas domyślna kompresja połączeń przez serwer WWW może wykazywać większą prędkość niż jest w rzeczywistości. Inną opcją jest użycie nieskompresowanego formatu pliku, np. Jpg. (dzięki Rauli Rajande za zwrócenie na to uwagi i Fluxine za przypomnienie )
Opisany powyżej mechanizm pomijania pamięci podręcznej może nie działać z niektórymi serwerami CDN, które można skonfigurować tak, aby ignorowały parametry ciągu zapytania, dlatego lepiej ustawić nagłówki kontroli pamięci podręcznej na samym obrazie. (dzięki orcaman za zwrócenie na to uwagi ) )
Cóż, to jest 2017 rok, więc masz teraz Network Information API (choć z ograniczoną obsługą w różnych przeglądarkach), aby uzyskać szacunkowe informacje o prędkości łącza w dół:
navigator.connection.downlink
Jest to efektywne oszacowanie przepustowości w Mb / s na sekundę. Przeglądarka dokonuje tego oszacowania na podstawie ostatnio zaobserwowanej przepustowości warstwy aplikacji dla ostatnio aktywnych połączeń. Nie trzeba dodawać, że największą zaletą tego podejścia jest to, że nie trzeba pobierać żadnych treści tylko w celu obliczenia przepustowości / prędkości.
Możesz zobaczyć to i kilka innych powiązanych atrybutów tutaj
Ze względu na ograniczoną obsługę i różne implementacje w różnych przeglądarkach (od listopada 2017 r.) Zdecydowanie zalecamy szczegółowe przeczytanie tego
Jak zarysowuję w tej innej odpowiedzi tutaj na StackOverflow , możesz to zrobić, odmierzając czas pobierania plików o różnych rozmiarach (zacznij od małego, zwiększ, jeśli połączenie wydaje się na to pozwalać), zapewniając przez nagłówki pamięci podręcznej i takie, że plik jest naprawdę czyta się ze zdalnego serwera i nie jest pobierana z pamięci podręcznej. Niekoniecznie wymaga to posiadania własnego serwera (pliki mogą pochodzić z S3 lub podobnego), ale będziesz potrzebować skądś, aby pobrać pliki, aby przetestować szybkość połączenia.
To powiedziawszy, testy przepustowości punktu w czasie są notorycznie niewiarygodne, ponieważ mają na nie wpływ inne elementy pobierane w innych oknach, prędkość serwera, łącza na trasie itp. Itp. Ale możesz mieć ogólny pomysł używając tego rodzaju techniki.
iframe
na przykład przesyłasz formularz do ukrytego , odpytujesz iframe
plik cookie lub plik cookie w celu uzupełnienia. Jeśli użyjesz XMLHttpRequest
obiektu do wykonania posta, nastąpi oddzwonienie do ukończenia.
Potrzebowałem szybkiego sposobu, aby ustalić, czy szybkość połączenia użytkownika jest wystarczająco duża, aby włączyć / wyłączyć niektóre funkcje w witrynie, nad którą pracuję. Stworzyłem ten mały skrypt, który uśrednia czas potrzebny do pobrania pojedynczego (małego) obrazu wiele razy działa całkiem dokładnie w moich testach, będąc w stanie wyraźnie odróżnić na przykład 3G lub Wi-Fi, może ktoś może stworzyć bardziej elegancką wersję, a nawet wtyczkę 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);
}
}
Sztuczka z obrazem jest fajna, ale w moich testach ładowała się przed niektórymi wywołaniami ajax, które chciałem zakończyć.
Właściwym rozwiązaniem w 2017 roku jest skorzystanie z pracownika ( http://caniuse.com/#feat=webworkers ).
Pracownik będzie wyglądał następująco:
/**
* 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
);
};
Plik js, który wywoła proces roboczy:
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);
}
};
Kod pobrany z pakietu Plone, który napisałem:
Lepiej jest używać obrazów do testowania prędkości. Ale jeśli masz do czynienia z plikami zip, poniższy kod działa.
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();
To nie będzie działać dobrze z plikami <10 MB. Będziesz musiał uruchomić zagregowane wyniki przy wielu próbach pobierania.
Potrzebowałem czegoś podobnego, więc napisałem https://github.com/beradrian/jsbandwidth . To jest przepisanie https://code.google.com/p/jsbandwidth/ .
Chodzi o to, aby wykonać dwa połączenia przez Ajax, jeden do pobrania, a drugi do przesłania przez POST.
Powinien działać z oboma jQuery.ajax
lub Angular $http
.
dzięki odpowiedzi Punit S, w celu wykrycia dynamicznej zmiany prędkości połączenia, możesz użyć następującego kodu:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}