Как определить скорость интернета в JavaScript?
Как я могу создать страницу JavaScript, которая будет определять скорость интернета пользователя и отображать ее на странице? Что-то вроде "ваша скорость интернета Кб / с ".
13 ответов
Это возможно в некоторой степени, но не очень точно, идея заключается в том, чтобы загрузить изображение с известным размером файла, а затем в его 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 год, так что теперь у вас есть API сетевой информации (хотя и с ограниченной поддержкой браузеров на данный момент), чтобы получить некоторую приблизительную информацию о скорости нисходящей линии связи:
navigator.connection.downlink
Это эффективная оценка пропускной способности в Мбит / с. Браузер делает эту оценку исходя из недавно наблюдаемой пропускной способности прикладного уровня по недавно активным соединениям. Само собой разумеется, что наибольшим преимуществом этого подхода является то, что вам не нужно загружать какой-либо контент только для расчета пропускной способности / скорости.
Вы можете посмотреть на это и несколько других связанных атрибутов здесь
Из-за ограниченной поддержки и различных реализаций в разных браузерах (по состоянию на ноябрь 2017 г.) настоятельно рекомендуем прочитать это подробно
Мне нужен был быстрый способ определить, была ли скорость соединения с пользователем достаточно высокой, чтобы включить / отключить некоторые функции на сайте, над которым я работаю, я сделал этот небольшой скрипт, который усредняет время, необходимое для загрузки одного (маленького) изображения в В моих тестах он работал довольно точно, например, он мог четко различать 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);
}
}
Как я обрисовал в общих чертах в этом другом ответе здесь, на Stackru, вы можете сделать это, синхронизируя загрузку файлов разных размеров (начните с малого, увеличивайте скорость, если кажется, что соединение разрешает это), гарантируя через заголовки кэша и такие, что файл действительно читается с удаленного сервера и не извлекается из кеша. Это не обязательно требует наличия собственного сервера (файлы могут быть с S3 или аналогичного), но вам нужно где-то получить файлы, чтобы проверить скорость соединения.
Тем не менее, тесты пропускной способности на определенный момент времени общеизвестно ненадежны, поскольку на них влияют другие элементы, загружаемые в другие окна, скорость вашего сервера, ссылки в пути и т. Д., И т. Д. Но вы можете получить приблизительное представление используя этот вид техники.
Несмотря на то, что это старый вопрос и на него есть ответ, я хотел бы поделиться решением, которое я сделал из него 2020
он обладает гибкостью для запуска в любое время и выполнения обратного вызова, если больше или меньше указанного Мбит / с
testConnectionSpeed:{
imageAddr : "/app/images/test_connection.jpg" ,
downloadSize : 31291,
run:function(mbps_max,cb_gt,cb_lt){
testConnectionSpeed.mbps_max = parseFloat(mbps_max) ? parseFloat(mbps_max) : 0;
testConnectionSpeed.cb_gt = cb_gt;
testConnectionSpeed.cb_lt = cb_lt;
testConnectionSpeed.InitiateSpeedDetection();
},
InitiateSpeedDetection: function() {
window.setTimeout(testConnectionSpeed.MeasureConnectionSpeed, 1);
},
result:function(){
var duration = (endTime - startTime) / 1000;
var bitsLoaded = testConnectionSpeed.downloadSize * 8;
var speedBps = (bitsLoaded / duration).toFixed(2);
var speedKbps = (speedBps / 1024).toFixed(2);
var speedMbps = (speedKbps / 1024).toFixed(2);
if(speedMbps >= (testConnectionSpeed.max_mbps ? testConnectionSpeed.max_mbps : 1) ){
testConnectionSpeed.cb_gt ? testConnectionSpeed.cb_gt() : false;
}else {
testConnectionSpeed.cb_lt ? testConnectionSpeed.cb_lt() : false;
}
},
MeasureConnectionSpeed:function() {
var download = new Image();
download.onload = function () {
endTime = (new Date()).getTime();
testConnectionSpeed.result();
}
startTime = (new Date()).getTime();
var cacheBuster = "?nnn=" + startTime;
download.src = testConnectionSpeed.imageAddr + cacheBuster;
}
}
затем вы можете запустить тест в любом месте после того, как вы добавили фрагмент выше, запустивtestConnectionSpeed.run(mbps, morefunction, lessfunction)
например:
testConnectionSpeed.run(1.5, function(){console.log(">= 1.5Mbps")}, function(){console.log("< 1.5Mbps")} )
(чем больше изображение, тем разумнее тест)
Трюк с изображением - это круто, но в моих тестах он загружался до некоторых вызовов ajax, которые я хотел завершить.
Правильное решение в 2017 году - использовать работника ( http://caniuse.com/).
Рабочий будет выглядеть так:
/**
* 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 МБ. Вам придется запускать агрегированные результаты при нескольких попытках загрузки.
Благодаря ответу Punit S, для определения динамического изменения скорости соединения вы можете использовать следующий код:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}
Улучшение ответа Джона Смита, красивое и чистое решение, которое возвращает обещание и, таким образом, может использоваться с
async/await
. Возвращает значение в Мбит / с.
const imageAddr = 'https://upload.wikimedia.org/wikipedia/commons/a/a6/Brandenburger_Tor_abends.jpg';
const downloadSize = 2707459; // this must match with the image above
let startTime, endTime;
async function measureConnectionSpeed() {
startTime = (new Date()).getTime();
const cacheBuster = '?nnn=' + startTime;
const download = new Image();
download.src = imageAddr + cacheBuster;
// this returns when the image is finished downloading
await download.decode();
endTime = (new Date()).getTime();
const duration = (endTime - startTime) / 1000;
const bitsLoaded = downloadSize * 8;
const speedBps = (bitsLoaded / duration).toFixed(2);
const speedMbps = (speedKbps / 1024).toFixed(2);
return Math.round(Number(speedMbps));
}
Мне нужно что-то подобное, поэтому я написал https://github.com/beradrian/jsbandwidth. Это переписать https://code.google.com/p/jsbandwidth/.
Идея состоит в том, чтобы сделать два вызова через Ajax, один для загрузки, а другой для загрузки через POST.
Это должно работать с обоими jQuery.ajax
или угловой $http
,
Вы можете определить время загрузки страницы. Попробуйте использовать следующий скрипт, чтобы измерить время, необходимое для полной загрузки страницы:
<html>
<head>
<script type="text/javascript">
var start = new Date().getTime();
function onLoad() {
var now = new Date().getTime();
var latency = now - start;
alert("page loading time: " + latency);
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
Смотрите страницу 3WC по времени навигации:
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
Мини-фрагмент:
var speedtest = {};
function speedTest_start(name) { speedtest[name]= +new Date(); }
function speedTest_stop(name) { return +new Date() - speedtest[name] + (delete
speedtest[name]?0:0); }
использовать как:
speedTest_start("test1");
// ... some code
speedTest_stop("test1");
// returns the time duration in ms
Также возможны дополнительные тесты:
speedTest_start("whole");
// ... some code
speedTest_start("part");
// ... some code
speedTest_stop("part");
// returns the time duration in ms of "part"
// ... some code
speedTest_stop("whole");
// returns the time duration in ms of "whole"