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

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

Ответ 1

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

Ответ 2

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

navigator.connection.downlink

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Это не очень хорошо работает с файлами < 10MB. Вам придется запускать агрегированные результаты при нескольких попытках загрузки.

Ответ 6

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

Ответ 7

Мне нужно что-то подобное, поэтому я написал https://github.com/beradrian/jsbandwidth. Это переписывание https://code.google.com/p/jsbandwidth/.

Идея состоит в том, чтобы сделать два вызова через Ajax, один для загрузки, а другой - через POST.

Он должен работать как с jQuery.ajax, так и с Angular $http.

Ответ 8

Вы можете определить время загрузки страницы. Попробуйте использовать следующий script, чтобы измерить время, необходимое для полной загрузки страницы:

<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

Ответ 9

благодаря ответу Punit S, для определения динамического изменения скорости соединения вы можете использовать следующий код:

navigator.connection.onchange = function () {
 //do what you need to do ,on speed change event
 console.log('Connection Speed Changed');
}