Làm cách nào để phát hiện tốc độ internet trong JavaScript?


213

Làm cách nào tôi có thể tạo một trang JavaScript sẽ phát hiện tốc độ internet của người dùng và hiển thị nó trên trang? Một cái gì đó giống như tốc độ internet của bạn là ?? / ?? Kb / sv .


1
@Jakub, @Ankit: Mọi người có thể sử dụng Flash cho nó, nhưng bạn không cần . Không có lý do gì bạn không thể làm điều đó với JavaScript.
TJ Crowder

Đây là những gì bạn cần: speedof.me/api.html
advncd

Câu trả lời:


287

Ở một mức độ nào đó có thể nhưng sẽ không thực sự chính xác, ý tưởng là tải hình ảnh với kích thước tệp đã biết sau đó trong onloadsự kiện của nó đo thời gian trôi qua cho đến khi sự kiện đó được kích hoạt và chia thời gian này cho kích thước tệp hình ảnh.

Ví dụ có thể được tìm thấy ở đây: Tính tốc độ bằng cách sử dụng javascript

Trường hợp thử nghiệm áp dụng các sửa chữa được đề xuất ở đó:

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

So sánh nhanh với dịch vụ kiểm tra tốc độ "thực" cho thấy sự khác biệt nhỏ 0,12 Mbps khi sử dụng hình ảnh lớn.

Để đảm bảo tính toàn vẹn của kiểm tra, bạn có thể chạy mã với công cụ điều chỉnh Chrome dev được bật và sau đó xem kết quả có khớp với giới hạn không. (tín dụng chuyển đến user284130 :))

Những điều quan trọng cần ghi nhớ:

  1. Hình ảnh đang được sử dụng phải được tối ưu hóa và nén đúng cách. Nếu không, thì nén mặc định trên các kết nối của máy chủ web có thể hiển thị tốc độ lớn hơn thực tế. Một tùy chọn khác là sử dụng định dạng tệp không nén được, ví dụ jpg. (cảm ơn Rauli Rajande đã chỉ ra điều này và Fluxine đã nhắc nhở tôi )

  2. Cơ chế buster cache được mô tả ở trên có thể không hoạt động với một số máy chủ CDN, có thể được cấu hình để bỏ qua các tham số chuỗi truy vấn, do đó tốt hơn là thiết lập các tiêu đề kiểm soát bộ đệm trên chính hình ảnh. (cảm ơn orcaman đã chỉ ra điều này ) )


8
Cẩn thận rằng hình ảnh thử nghiệm được tối ưu hóa và nén đúng cách. Nếu không, thì nén mặc định trên các kết nối bởi máy chủ web có thể hiển thị tốc độ lớn hơn thực tế.
Rauli Rajande

3
Tôi đã tìm thấy một mẹo nhỏ để đảm bảo hình ảnh của bạn phù hợp với thử nghiệm: chạy mã với công cụ điều chỉnh Chrome dev được bật và xem kết quả có khớp với giới hạn không. Hy vọng điều này có thể giúp ai đó.
dùng284130

3
tham gia Rauli Rajande: sử dụng tốt hơn một tệp không thể nén (hoặc gần như) hoặc các mô-đun nén máy chủ web có thể làm giảm đáng kể, làm mất hiệu lực của biện pháp. Một hình ảnh jpeg sẽ là một lựa chọn tốt.
Fluxine 6/2/2015

1
Đối với những người đã sử dụng thành công mã Javascript này, ban đầu bạn có gặp phải cuộc gọi nào không đến "download.onload" không? Đây chính xác là những gì tôi đang trải nghiệm và tôi vẫn đang cố gắng tìm hiểu tại sao.

2
@Dilip hình ảnh nhỏ hơn có nghĩa là thử nghiệm ít chính xác hơn, đó là mục đích lớn. :)
Shadow Wizard là Ear For You

78

Chà, đây là năm 2017 nên hiện tại bạn đã có API Thông tin mạng (mặc dù có hỗ trợ hạn chế trên các trình duyệt) để có được một số loại thông tin tốc độ đường xuống ước tính :

navigator.connection.downlink

Đây là ước tính băng thông hiệu quả tính bằng Mbits mỗi giây. Trình duyệt đưa ra ước tính này từ thông lượng của lớp ứng dụng được quan sát gần đây trên các kết nối hoạt động gần đây. Không cần phải nói, ưu điểm lớn nhất của phương pháp này là bạn không cần tải xuống bất kỳ nội dung nào chỉ để tính toán băng thông / tốc độ.

Bạn có thể xem xét điều này và một vài thuộc tính liên quan khác ở đây

Do đó là hỗ trợ giới hạn và triển khai khác nhau trên các trình duyệt (tính đến tháng 11 năm 2017), rất muốn giới thiệu đọc này một cách chi tiết


18
Đó là rất nhiều màu đỏ trong Tôi có thể sử dụng!
Francisco Presencia

2
Tôi không nhận được số cao hơn 10MBit bằng cách này. Có giới hạn không?
Tobi

@Tobi Tôi dường như cũng không nhận được cao hơn 10MBit, nên giống như 100MBit
camjocotem

Chính xác đường xuống là gì? Là tốc độ tải xuống hay cái gì đó?
gacat

@Tobi Tôi cũng vậy, nếu tốc độ trên 10Mb tôi cứ đọc 10
Aramil

21

Như tôi phác thảo trong câu trả lời khác ở đây trên StackOverflow , bạn có thể thực hiện việc này bằng cách định thời gian tải xuống các tệp có kích thước khác nhau (bắt đầu nhỏ, tăng tốc nếu kết nối dường như cho phép), đảm bảo thông qua các tiêu đề bộ đệm và sao cho tệp thực sự được đọc từ máy chủ từ xa và không được truy xuất từ ​​bộ đệm. Điều này không nhất thiết yêu cầu bạn phải có máy chủ của riêng mình (các tệp có thể đến từ S3 hoặc tương tự), nhưng bạn sẽ cần một nơi nào đó để lấy các tệp từ đó để kiểm tra tốc độ kết nối.

Điều đó nói rằng, kiểm tra băng thông tại thời điểm nổi tiếng là không đáng tin cậy, vì chúng bị ảnh hưởng bởi các mục khác được tải xuống trong các cửa sổ khác, tốc độ của máy chủ của bạn, liên kết trên đường, v.v., nhưng bạn có thể hiểu sơ bộ sử dụng loại kỹ thuật này.


1
@Jakub: Bạn sẽ phải có một nơi để tải lên, nhưng không có lý do gì bạn không thể sử dụng kỹ thuật tương tự cho việc đó. Bạn có thể sử dụng dữ liệu bạn tạo nhanh chóng hoặc tất nhiên, bạn có thể sử dụng lại một số dữ liệu bạn đã tải xuống để kiểm tra tải xuống.
TJ Crowder

Vậy làm thế nào bạn biết khi nào tải lên hoàn thành?
Jakub Hampl

2
@Jakub: Bất kỳ cách nào. iframeVí dụ: nếu bạn gửi biểu mẫu cho một ẩn , bạn sẽ thăm dò ý kiến iframehoặc cookie để hoàn thành. Nếu bạn sử dụng một XMLHttpRequestđối tượng để thực hiện bài đăng, sẽ có một cuộc gọi lại để hoàn thành.
TJ Crowder

17

Tôi cần một cách nhanh chóng để xác định xem tốc độ kết nối của người dùng có đủ nhanh để bật / tắt một số tính năng trong trang web tôi đang làm hay không, tôi đã tạo tập lệnh nhỏ này tính trung bình thời gian cần để tải xuống một hình ảnh (nhỏ) nhiều lần, nó hoạt động khá chính xác trong các thử nghiệm của tôi, ví dụ như có thể phân biệt rõ ràng giữa 3G hoặc Wi-Fi, có thể ai đó có thể tạo phiên bản thanh lịch hơn hoặc thậm chí là một 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
Câu trả lời đáng tin cậy nhất, trong trường hợp của tôi.
Abdalla Arbab

1
Còn bài kiểm tra tải lên thì sao?
gumuruh

9

Thủ thuật hình ảnh rất tuyệt nhưng trong các thử nghiệm của tôi, nó đã được tải trước khi một số cuộc gọi ajax tôi muốn hoàn thành.

Giải pháp thích hợp trong năm 2017 là sử dụng một công nhân ( http://caniuse.com/#feat=webworkers ).

Công nhân sẽ trông như:

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

Tệp js sẽ gọi 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);
  }
};

Mã được lấy từ gói Plone tôi đã viết:


5

Tốt hơn là sử dụng hình ảnh để kiểm tra tốc độ. Nhưng nếu bạn phải xử lý các tệp zip, đoạn mã dưới đây hoạt động.

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

Điều này sẽ không hoạt động tốt với các tệp <10MB. Bạn sẽ phải chạy kết quả tổng hợp trên nhiều lần tải xuống.


3
Tôi thực sự thích sự đơn giản của câu trả lời và tôi đã điều chỉnh nó cho mục đích của mình: Tôi đã đổi sang window.performance.now cho dấu thời gian, request.responseType = "blob" (loại MIME không hợp lệ), request.response.size cho kích thước tải xuống và 1000000 cho tính toán tốc độ (vì Mbps phải ở đơn vị SI).
Rupert Rawnsley


1

nhờ câu trả lời của Punit S, để phát hiện thay đổi tốc độ kết nối động, bạn có thể sử dụng mã sau:

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

2
Thật không may, nó không hỗ trợ tất cả các trình duyệt. caniuse.com/#search=netinfo
axelioo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.