Как я могу создать страницу 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. (спасибо Rauli Rajande за указание на это и Fluxine за напоминание )
Описанный выше механизм блокировки кэша может не работать с некоторыми серверами CDN, которые можно настроить так, чтобы они игнорировали параметры строки запроса, следовательно, лучше настраивать заголовки управления кэшем на самом изображении. (спасибо orcaman за указание на это ) )
Ну, это так , 2017 года вы теперь Network Information API (хотя и с ограниченной поддержкой различных браузеров , как сейчас) , чтобы получить какое - то оценку информации о скорости нисходящей линии:
navigator.connection.downlink
Это эффективная оценка пропускной способности в Мбит / с. Браузер делает эту оценку исходя из недавно наблюдаемой пропускной способности уровня приложения по недавно активным соединениям. Само собой разумеется, что наибольшим преимуществом этого подхода является то, что вам не нужно загружать контент только для расчета пропускной способности / скорости.
Вы можете посмотреть на это и несколько других связанных атрибутов здесь
Из-за ограниченной поддержки и различных реализаций в браузерах (по состоянию на ноябрь 2017 г.), настоятельно рекомендую прочитать это подробно
Как я обрисовал в общих чертах в этом другом ответе здесь, на StackOverflow , вы можете сделать это, синхронизируя загрузку файлов разных размеров (начните с малого, увеличивайте скорость, если кажется, что соединение разрешает это), гарантируя через заголовки кэша и такие, что файл действительно читается с удаленного сервера и не извлекается из кеша. Это не обязательно требует наличия собственного сервера (файлы могут быть с S3 или аналогичного), но вам нужно где-то получить файлы, чтобы проверить скорость соединения.
Тем не менее, тесты пропускной способности на определенный момент времени, как известно, ненадежны, поскольку на них влияют другие элементы, загружаемые в другие окна, скорость вашего сервера, ссылки в пути и т. Д., И т. Д. Но вы можете получить приблизительное представление используя этот вид техники.
iframe
Например, если вы отправляете скрытую форму , вы опрашиваете iframe
или файл 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, который я написал:
Для проверки скорости лучше использовать изображения. Но если вам приходится иметь дело с zip-файлами, приведенный ниже код работает.
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');
}