Як я можу створити сторінку 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');
}