JavaScript에서 인터넷 속도를 감지하는 방법?


213

사용자의 인터넷 속도를 감지하여 페이지에 표시 할 JavaScript 페이지를 어떻게 만들 수 있습니까? 같은 뭔가 "인터넷 속도는 ?? / ??입니다 Kb / s” .


1
@Jakub, @Ankit : 사람들은 Flash를 사용할 수 있지만 꼭 그럴 필요 는 없습니다 . JavaScript로 할 수없는 이유는 없습니다.
TJ Crowder

이것은 당신이 필요한 것입니다 : speedof.me/api.html
advncd

답변:


287

어느 정도 가능하지만 실제로는 정확하지는 않습니다. 아이디어는 알려진 파일 크기의 이미지를로드 한 다음 onload이벤트 에서 해당 이벤트가 트리거 될 때까지 경과 된 시간을 측정 하고이 시간을 이미지 파일 크기로 나눕니다.

예제는 여기에서 찾을 수 있습니다 : 자바 스크립트를 사용하여 속도 계산

수정 사항을 적용한 테스트 사례는 다음과 같습니다.

//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.12Mbps의 작은 차이를 보여주었습니다.

테스트의 무결성을 보장하기 위해 Chrome 개발 도구 조절 기능을 사용하여 코드를 실행 한 다음 결과가 제한과 일치하는지 확인할 수 있습니다. (신용은 user284130 로갑니다. )

명심해야 할 사항 :

  1. 사용되는 이미지는 적절하게 최적화되고 압축되어야합니다. 그렇지 않은 경우 웹 서버에 의한 연결에서 기본 압축이 실제보다 더 큰 속도를 표시 할 수 있습니다. 다른 옵션은 압축되지 않는 파일 형식 (예 : jpg)을 사용하는 것입니다. (Rauli Rajande에게 이것을 지적 해 주셔서 감사 하고 Fluxine에게 상기시켜 주셔서 감사 합니다 )

  2. 위에서 설명한 캐시 버스터 메커니즘은 일부 CDN 서버에서 작동하지 않을 수 있으며, 이는 쿼리 문자열 매개 변수를 무시하도록 구성 될 수 있으므로 이미지 자체에 캐시 제어 헤더를 설정하는 것이 좋습니다. (orcaman에게 이것을 지적 해 주셔서 감사 합니다 ) )


8
테스트 이미지가 올바르게 최적화되고 압축되었는지 확인하십시오. 그렇지 않은 경우 웹 서버 연결의 기본 압축 속도가 실제 속도보다 더 빠를 수 있습니다.
Rauli Rajande

3
Chrome 개발자 도구 조절 기능을 사용하여 코드를 실행하고 결과가 제한과 일치하는지 확인하십시오. 이것이 누군가를 도울 수 있기를 바랍니다.
user284130

3
Rauli Rajande 가입 : 압축 할 수없는 (또는 거의) 파일을 더 잘 사용하십시오. 그렇지 않으면 웹 서버 압축 모듈이 파일을 크게 줄여 측정을 무효화 할 수 있습니다. jpeg 이미지가 좋은 선택입니다.
Fluxine

1
이 Javascript 코드를 성공적으로 사용한 사용자의 경우 처음에 "download.onload"로 이동하는 호출이 없었습니까? 이것은 내가 겪고있는 것과 정확하게 이유를 찾으려고 노력하고 있습니다.

2
@Dilip 이미지가 작을수록 테스트 정확도가 떨어지며 의도적으로 큰 것입니다. :)
그림자 마법사 귀는 당신을위한

78

당신은 지금 (지금과 같은 브라우저에서 제한된 지원을이기는하지만) 네트워크 정보 API가 어떤 종류의 얻을 수 있도록 음,이 2017 인 추정치 하향 속도 정보를 :

navigator.connection.downlink

이는 초당 Mbits의 유효 대역폭 추정치입니다. 브라우저는 최근에 활성화 된 연결에서 최근에 관찰 된 응용 프로그램 계층 처리량을 통해이 추정치를 만듭니다. 말할 필요도없이,이 방법의 가장 큰 장점은 대역폭 / 속도 계산을 위해 콘텐츠를 다운로드 할 필요가 없다는 것입니다.

여기 에서 몇 가지 다른 관련 속성을 볼 수 있습니다.

그것은 (년 11 월 2017로) 브라우저에서 제한적으로 지원하고 다른 구현을의에 강력하게 추천 할 것입니다 인해 것은 읽는 이를 자세히


18
그것은 내가 사용할 수있는 많은 빨간색입니다!
Francisco Presencia 2016 년

2
이것을 사용하여 10MBit보다 높은 숫자는 얻지 못합니다. 한도가 있습니까?
Tobi

@Tobi 나도 10MBit 이상으로 올라가지 않는 것 같습니다. 100MBit 이상이어야합니다.
camjocotem

다운 링크 란 정확히 무엇입니까? 다운로드 속도입니까?
gacat

@Tobi 저도, 속도가 10Mb를 넘으면
Aramil

21

StackOverflow에 대한이 다른 답변 에서 간략하게 설명했듯이 다양한 크기의 파일 다운로드 (소형 시작, 연결이 허용되는 경우 램프 업) 타이밍을 지정하여 캐시 헤더를 통해 파일을 실제로 확인 함으로써이 작업을 수행 할 수 있습니다 원격 서버에서 읽고 캐시에서 검색하지 않습니다. 반드시 서버가 필요하지는 않지만 (파일이 S3 또는 이와 유사한 것일 수 있음 ) 연결 속도를 테스트하려면 파일을 가져올 수있는 곳이 필요합니다.

즉, 특정 시점 대역폭 테스트는 다른 창에서 다운로드되는 다른 항목, 서버 속도, 링크 경로 등의 영향을 받기 때문에 신뢰할 수없는 것으로 악명 높지만, 대략적인 아이디어를 얻을 수 있습니다. 이런 종류의 기술을 사용합니다.


1
@Jakub : 업로드 할 장소가 있어야하지만 동일한 기술을 사용할 수있는 이유는 없습니다. 직접 생성 한 데이터를 사용하거나 다운로드 테스트를 위해 다운로드 한 일부 데이터를 재사용 할 수 있습니다.
TJ Crowder

업로드가 언제 완료되었는지 어떻게 알 수 있습니까?
Jakub Hampl

2
@Jakub : 여러 가지 방법 중 하나. iframe예를 들어, 숨겨진에 양식 제출을 수행하는 경우 iframe완료를 위해 또는 쿠키를 폴링합니다 . XMLHttpRequest개체를 사용 하여 게시물을 작성하는 경우 완료를위한 콜백이 있습니다.
TJ Crowder

17

작업중인 사이트의 일부 기능을 활성화 / 비활성화 할 수있을 정도로 사용자 연결 속도가 빠른지 확인하는 빠른 방법이 필요했습니다.이 작은 스크립트를 작성하여 단일 (작은) 이미지를 다운로드하는 데 걸리는 시간을 평균화했습니다. 여러 번, 테스트에서 꽤 정확하게 작동하여 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);
  }
}


1
내 경우에는 가장 신뢰할 수있는 대답.
Abdalla Arbab

1
업로드 테스트는 어떻습니까?
gumuruh

9

이미지 트릭은 멋지지만 내 테스트에서는 일부 아약스 호출 전에 완료되고 싶었습니다.

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

Worker를 호출 할 js 파일 :

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 패키지에서 가져온 코드 :


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 미만의 파일에서는 제대로 작동하지 않습니다. 여러 번의 다운로드 시도에서 집계 된 결과를 실행해야합니다.


3
정말 답의 단순성과 같은 I 나는 내 목적을 위해 그것을 적응 : 내가하는 교환 window.performance.now 타임 스탬프에 대한 request.responseType = "덩어리" , (MIME 유형은 유효하지 않은) request.response.size을 위한 다운로드 크기 및 속도 계산의 경우 1000000 (Mbps는 SI 단위 여야하므로).
Rupert Rawnsley


1

동적 연결 속도 변화를 감지하는 Punit S 응답 덕분에 다음 코드를 사용할 수 있습니다.

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

2
불행히도 모든 브라우저를 지원하지는 않습니다. caniuse.com/#search=netinfo
axelioo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.