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

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



답변

어느 정도 가능하지만 실제로는 정확하지는 않습니다. 아이디어는 알려진 파일 크기의 이미지를로드 한 다음 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에게 이것을 지적 해 주셔서 감사 합니다 ) )


답변

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

navigator.connection.downlink

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

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

그것은 (년 11 월 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);
  }
}


답변

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

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


답변

속도를 테스트하기 위해 이미지를 사용하는 것이 좋습니다. 그러나 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 미만의 파일에서는 제대로 작동하지 않습니다. 여러 번의 다운로드 시도에서 집계 된 결과를 실행해야합니다.


답변

비슷한 것이 필요했기 때문에 https://github.com/beradrian/jsbandwidth을 작성했습니다 . https://code.google.com/p/jsbandwidth/를 다시 작성했습니다 .

아이디어는 Ajax를 통해 두 번, 하나는 다운로드하고 다른 하나는 POST를 통해 업로드하는 것입니다.

둘 다 jQuery.ajax또는 Angular 와 함께 작동해야합니다 $http.