Как определить скорость интернета в JavaScript?

Как создать страницу JavaScript, которая определит скорость интернета пользователя и покажет ее на странице? Что-то вроде " ваша скорость интернета ??/?? Кб/с".

8 ответов


это возможно в некоторой степени, но не будет действительно точным, идея-загрузить изображение с известным размером файла, а затем в его 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, а затем посмотреть, соответствует ли результат ограничению. (заслуга user284130 :))

важные вещи, чтобы иметь в виду:

  1. изображение должно быть правильно оптимизированы и сжаты. Если это нет, тогда сжатие по умолчанию для соединений веб-сервером может показывать скорость больше, чем на самом деле. Другой вариант-это использовать формат uncompressible файл, например jpg. (спасибо Раули Раджанде за обратите внимание и Fluxine для напоминаешь мне)

  2. механизм Cache buster, описанный выше, может не работать с некоторыми серверами CDN, которые могут быть настроены для игнорирования параметров строки запроса, следовательно лучше устанавливать заголовки управления кэшем на самом изображении. (спасибо orcaman за обратите внимание))


Ну, это 2017, поэтому теперь у вас есть API сетевой информации (хотя и с ограниченной поддержкой браузеров на данный момент), чтобы получить какой-то оценка информация о скорости нисходящей линии связи:

navigator.connection.downlink

это эффективная оценка пропускной способности в Мбит / с. Браузер делает эту оценку из недавно наблюдаемой пропускной способности уровня приложения через недавно активные соединения. Излишне говорить, самым большим преимуществом этого подхода является то, что вам не нужно загружать любое контент только для расчета пропускной способности / скорости.

вы можете посмотреть на это и несколько других связанных атрибутов здесь

из-за его ограниченной поддержки и различных реализаций в браузерах (по состоянию на ноябрь 2017 года), настоятельно рекомендуем Вам прочитать этой подробно


Как я описываю в этот другой ответ здесь, на StackOverflow, вы можете сделать это, синхронизируя загрузку файлов различных размеров (начните с малого, увеличьте, если соединение, кажется, позволяет это), гарантируя через заголовки кэша и таким образом, что файл действительно считывается с удаленного сервера и не извлекается из кэша. Это не обязательно требует, чтобы у вас был собственный сервер (файлы могут поступать из S3 или аналогичный), но вам понадобится где-то, чтобы получить файлы, чтобы проверить скорость соединения.

тем не менее, точечные тесты пропускной способности, как известно, ненадежны, поскольку на них влияют другие элементы, загружаемые в других окнах, скорость вашего сервера, ссылки в пути и т. д., п. Но вы можете получить приблизительное представление, используя такую технику.


Мне нужен был быстрый способ определить, была ли скорость подключения пользователя достаточно быстрой, чтобы включить/отключить некоторые функции на сайте, над которым я работаю, я сделал этот маленький скрипт, который в среднем занимает время, необходимое для загрузки одного (небольшого) изображения несколько раз, он работает довольно точно в моих тестах, будучи в состоянии четко различать 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);
    }
}   

лучше использовать изображения для тестирования скорости. Но если вам приходится иметь дело с 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();

Это не будет работать очень хорошо с файлами


трюк с изображением классный, но в моих тестах он загружался до некоторых вызовов 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 I написал:


мне нужно было что-то подобное, поэтому я написал 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