Як я можу створити сторінку JavaScript, яка буде визначати швидкість інтернету користувача та показувати його на сторінці? Щось на кшталт "швидкість вашого Інтернету є ?? / ?? Кб / с ” .
Як я можу створити сторінку JavaScript, яка буде визначати швидкість інтернету користувача та показувати його на сторінці? Щось на кшталт "швидкість вашого Інтернету є ?? / ?? Кб / с ” .
Відповіді:
Це можливо до певної міри, але не буде по-справжньому точним, ідея полягає у завантаженні зображення з відомим розміром файлу, а потім у його onloadвипадку вимірюють скільки часу минуло до того, як ця подія була запущена, і розділити цей час на розмір файлу зображення.
Приклад можна знайти тут: Обчисліть швидкість за допомогою javascript
Тестовий випадок із застосуванням запропонованого виправлення:
//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>
Швидке порівняння з "реальною" послугою тестування швидкості показало невелику різницю 0,12 Мбіт / с при використанні великої картини.
Щоб забезпечити цілісність тесту, ви можете запустити код із увімкненим утисканням інструмента Chrome dev, а потім побачити, чи відповідає результат обмеженню. (кредит надається користувачу284130 :))
Важливі речі, про які слід пам’ятати:
Зображення, яке використовується, має бути належним чином оптимізовано та стиснене. Якщо це не так, то компресія за замовчуванням на з'єднаннях веб-сервером може виявити швидкість, більшу, ніж є насправді. Інший варіант - використання форматного файлу, що не стискається, наприклад, jpg. (дякую Раулі Раджанде, що вказав на це, і Флуксин, що нагадав мені )
Описаний вище механізм розгортання кешу може не працювати з деякими серверами CDN, які можна налаштувати на ігнорування параметрів рядка запиту, отже, краще встановити заголовки кеш-керування для самого зображення. (дякую orcaman за вказівку на це ) )
Ну, це 2017 рік, тож тепер у вас є API інформації про мережу (хоч і з обмеженою підтримкою в браузерах на сьогодні), щоб отримати якесь оцінку інформації про швидкості низхідній лінії:
navigator.connection.downlink
Це ефективна оцінка пропускної здатності в Мбіт / с. Веб-переглядач робить цю оцінку за останнім часом спостережуваного рівня програми через останні активні з'єднання. Потрібно сказати, що найбільшою перевагою такого підходу є те, що вам не потрібно завантажувати будь-який вміст лише для обчислення пропускної здатності / швидкості.
Ви можете ознайомитись із цим та парою інших пов’язаних атрибутів тут
З - за його обмежену підтримку і різних реалізацій в різних браузерах (за станом на листопад 2017 року), настійно рекомендую прочитати це докладно
Як я окреслюю в цій іншій відповіді тут на StackOverflow , ви можете зробити це, встановивши тимчасове завантаження файлів різного розміру (почніть невеликий, нарощуйте, якщо з'єднання здається, що це дозволяє), забезпечивши через заголовки кешу і таке, що файл справді читається з віддаленого сервера і не витягується з кешу. Це не обов'язково вимагає наявності власного сервера (файли можуть надходити з S3 або подібного), але вам потрібно буде десь дістати файли, щоб перевірити швидкість з'єднання.
Однак, тести пропускної спроможності в часі часу є сумнівно ненадійними, оскільки на них впливають інші елементи, які завантажуються в інші вікна, швидкість роботи вашого сервера, посилання на маршруті тощо тощо. Але ви можете отримати орієнтовне уявлення використовуючи цю техніку.
iframe, наприклад, ви опитуєте iframeфайл cookie або файл cookie для його заповнення. Якщо ви використовуєте XMLHttpRequestоб'єкт для публікації, є зворотний виклик для завершення.
Мені потрібен був швидкий спосіб визначити, чи була швидкість з'єднання користувачів достатньо швидкою, щоб увімкнути / вимкнути деякі функції на веб-сайті, над яким я працюю, я створив цей маленький сценарій, який в середньому витрачає час на завантаження одного (невеликого) зображення У багатьох тестах вона працює досить точно, маючи можливість чітко розмежувати наприклад 3G або Wi-Fi, можливо, хтось може зробити більш елегантну версію або навіть плагін 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);
}
}
Зображення хитрощі, але в моїх тестах він завантажувався до деяких дзвінків в Ajax, які я хотів завершити.
Правильне рішення у 2017 році - використовувати працівника ( http://caniuse.com/#feat=webworkers ).
Працівник буде виглядати так:
/**
* 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
);
};
Файл js, який викликатиме 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);
}
};
Код, взятий із пакета Plone, я написав:
Краще використовувати зображення для тестування швидкості. Але якщо вам доведеться мати справу з поштовими файлами, наведений нижче код працює.
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();
Це не дуже добре працюватиме з файлами <10 Мб. Вам доведеться запускати зведені результати при кількох спробах завантаження.
Мені потрібно було щось подібне, тому я написав https://github.com/beradrian/jsbandwidth . Це перезапис https://code.google.com/p/jsbandwidth/ .
Ідея полягає у тому, щоб зробити два дзвінки через Ajax, один для завантаження та інший для завантаження через POST.
Він повинен працювати з обома jQuery.ajaxабо кутовими $http.
завдяки відповіді Punit S для виявлення динамічної зміни швидкості з'єднання можна використовувати такий код:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}