Bagaimana cara mendeteksi kecepatan internet dalam JavaScript?


214

Bagaimana saya bisa membuat halaman JavaScript yang akan mendeteksi kecepatan internet pengguna dan menampilkannya di halaman? Sesuatu seperti "kecepatan internet Anda adalah ?? / ?? Kb / s ” .


1
@ Jakub, @Ankit: Orang mungkin menggunakan Flash untuk itu, tetapi Anda tidak perlu melakukannya. Tidak ada alasan apa pun yang tidak dapat Anda lakukan dengan JavaScript.
TJ Crowder

Inilah yang Anda butuhkan: speedof.me/api.html
advncd

Jawaban:


288

Mungkin sampai batas tertentu tetapi tidak akan benar-benar akurat, idenya adalah memuat gambar dengan ukuran file yang diketahui kemudian onloadmengukur peristiwa berapa banyak waktu berlalu sampai peristiwa itu dipicu, dan membagi waktu ini dalam ukuran file gambar.

Contoh dapat ditemukan di sini: Hitung kecepatan menggunakan javascript

Test case menerapkan perbaikan yang disarankan di sana:

//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>

Perbandingan cepat dengan layanan tes kecepatan "nyata" menunjukkan perbedaan kecil 0,12 Mbps saat menggunakan gambar besar.

Untuk memastikan integritas pengujian, Anda dapat menjalankan kode dengan pelambatan alat dev dev Chrome dan kemudian melihat apakah hasilnya cocok dengan batasan. (kredit masuk ke user284130 :))

Hal-hal penting yang perlu diingat:

  1. Gambar yang digunakan harus dioptimalkan dan dikompresi dengan benar. Jika tidak, maka kompresi standar pada koneksi oleh server web mungkin menunjukkan kecepatan lebih besar dari yang sebenarnya. Pilihan lain adalah menggunakan format file yang tidak dapat dikompres, misalnya jpg. (Terima kasih Rauli Rajande karena menunjukkan ini dan Fluxine karena mengingatkan saya )

  2. Mekanisme cache buster yang dijelaskan di atas mungkin tidak berfungsi dengan beberapa server CDN, yang dapat dikonfigurasikan untuk mengabaikan parameter string kueri, karenanya mengatur header kontrol cache yang lebih baik pada gambar itu sendiri. (Terima kasih orcaman untuk menunjukkan ini ) )


8
Berhati-hatilah agar gambar uji dioptimalkan dan dikompres dengan benar. Jika tidak, maka kompresi default pada koneksi dengan server web mungkin menunjukkan kecepatan lebih besar dari yang sebenarnya.
Rauli Rajande

3
Saya menemukan sedikit trik untuk memastikan gambar Anda sesuai untuk pengujian: jalankan kode dengan pelambatan alat dev dev Chrome, dan lihat apakah hasilnya sesuai dengan batasan. Semoga ini bisa membantu seseorang.
user284130

3
bergabung dengan Rauli Rajande: lebih baik gunakan file yang tidak dapat dikompresi (atau hampir), atau modul kompresi server web dapat mengurangi secara signifikan, membatalkan pengukuran. Gambar jpeg akan menjadi pilihan yang baik.
Fluxine

1
Bagi mereka yang telah berhasil menggunakan kode Javascript ini, apakah Anda awalnya tidak menemukan panggilan yang akan "unduh.onload"? Ini persis apa yang saya alami dan saya masih berusaha mencari tahu mengapa.

2
@Dilip gambar yang lebih kecil berarti tes yang kurang akurat, itu besar sengaja. :)
Shadow Wizard adalah Ear For You

78

Nah, ini tahun 2017 sehingga Anda sekarang memiliki API Informasi Jaringan (walaupun dengan dukungan terbatas di semua browser seperti sekarang) untuk mendapatkan semacam perkiraan informasi kecepatan downlink:

navigator.connection.downlink

Ini adalah perkiraan bandwidth efektif dalam Mbits per detik. Browser membuat perkiraan ini dari throughput lapisan aplikasi yang baru-baru ini diamati melalui koneksi yang baru-baru ini aktif. Tidak perlu dikatakan, keuntungan terbesar dari pendekatan ini adalah Anda tidak perlu mengunduh konten apa pun hanya untuk perhitungan bandwidth / kecepatan.

Anda dapat melihat ini dan beberapa atribut terkait lainnya di sini

Karena dukungannya yang terbatas dan implementasi yang berbeda di seluruh browser (pada Nov 2017), sangat disarankan untuk membaca ini secara detail


18
Itu banyak warna merah yang bisa saya gunakan!
Francisco Presencia

2
Saya tidak mendapatkan angka lebih tinggi dari 10 MB menggunakan ini. Apakah ada batasannya?
Tobi

@Tobi Saya juga sepertinya tidak mendapatkan yang lebih tinggi dari 10MBit, seharusnya lebih seperti 100MBit
camjocotem

Apa sebenarnya downlink itu? Apakah kecepatan unduh atau apalah?
gacat

@ Tobi Me juga, jika kecepatannya lebih dari 10MB saya terus membaca 10
Aramil

21

Seperti yang saya uraikan dalam jawaban lain di sini di StackOverflow , Anda dapat melakukan ini dengan mengatur waktu pengunduhan file dari berbagai ukuran (mulai dari yang kecil, tingkatkan jika koneksi tampaknya memungkinkan), memastikan melalui header cache dan sedemikian rupa sehingga file tersebut benar-benar sedang dibaca dari server jarak jauh dan tidak diambil dari cache. Ini tidak selalu mengharuskan Anda memiliki server sendiri (file mungkin berasal dari S3 atau serupa), tetapi Anda akan memerlukan tempat untuk mendapatkan file untuk menguji kecepatan koneksi.

Yang mengatakan, tes bandwidth point-in-time terkenal tidak dapat diandalkan, karena mereka dipengaruhi oleh item lain yang diunduh di windows lain, kecepatan server Anda, tautan dalam perjalanan, dll., Dll. Tetapi Anda bisa mendapatkan ide kasar menggunakan teknik semacam ini.


1
@ Yakub: Anda harus memiliki tempat untuk mengunggah, tetapi tidak ada alasan Anda tidak dapat menggunakan teknik yang sama untuk itu. Anda dapat menggunakan data yang Anda hasilkan secara langsung atau, tentu saja, Anda dapat menggunakan kembali beberapa data yang Anda unduh untuk uji unduhan.
TJ Crowder

Jadi, bagaimana Anda tahu kapan unggahan selesai?
Jakub Hampl

2
@ Jakub: Ada beberapa cara. Jika Anda melakukan pengiriman formulir ke tersembunyi iframe, misalnya, Anda polling iframeatau cookie untuk selesai. Jika Anda menggunakan XMLHttpRequestobjek untuk melakukan posting, ada panggilan balik untuk diselesaikan.
TJ Crowder

18

Saya memerlukan cara cepat untuk menentukan apakah kecepatan koneksi pengguna cukup cepat untuk mengaktifkan / menonaktifkan beberapa fitur di situs yang saya kerjakan, saya membuat skrip kecil ini yang rata-rata waktu yang diperlukan untuk mengunduh satu (kecil) gambar beberapa kali, ini berfungsi cukup akurat dalam pengujian saya, bisa membedakan dengan jelas antara 3G atau Wi-Fi misalnya, mungkin seseorang dapat membuat versi yang lebih elegan atau bahkan plugin 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);
  }
}


1
Jawaban yang paling dapat diandalkan, dalam kasus saya.
Abdalla Arbab

1
bagaimana dengan tes pengunggahan?
gumuruh

9

Trik gambarnya keren tetapi dalam pengujian saya memuat sebelum beberapa panggilan ajax saya ingin selesai.

Solusi yang tepat di 2017 adalah menggunakan pekerja ( http://caniuse.com/#feat=webworkers ).

Pekerja akan terlihat seperti:

/**
 * 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
  );
};

File js yang akan memanggil Pekerja:

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);
  }
};

Kode diambil dari paket Plone yang saya tulis:


5

Lebih baik menggunakan gambar untuk menguji kecepatan. Tetapi jika Anda harus berurusan dengan file zip, kode di bawah ini berfungsi.

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();

Ini tidak akan bekerja dengan baik dengan file <10MB. Anda harus menjalankan hasil agregat pada beberapa upaya unduhan.


3
Saya sangat menyukai kesederhanaan jawaban dan saya telah mengadaptasinya untuk tujuan saya: saya bertukar ke window.performance.now untuk cap waktu, request.responseType = "gumpalan" (tipe MIME tidak valid), request.response.size untuk ukuran unduhan, dan 1000000 untuk perhitungan kecepatan (karena Mbps harus dalam satuan SI).
Rupert Rawnsley


1

berkat jawaban Punit S, untuk mendeteksi perubahan kecepatan koneksi dinamis, Anda dapat menggunakan kode berikut:

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

2
sayangnya itu tidak mendukung semua browser. caniuse.com/#search=netinfo
axelioo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.