programing

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

procenter 2023. 1. 3. 22:22
반응형

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

사용자의 인터넷 속도를 감지하여 페이지에 표시하는 JavaScript 페이지를 작성하려면 어떻게 해야 합니까?예를 들어 "인터넷 속도가 ?/Kb/s"와 같습니다.

어느 정도 가능하지만 정확하지는 않습니다.이미지의 로드와 파일 사이즈를 알고 있습니다.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>

'실제' 속도 테스트 서비스와 빠르게 비교한 결과 빅픽처 사용 시 0.12Mbps로 차이가 작았다.

테스트의 무결성을 보장하기 위해 Chrome 개발 도구 조절을 사용하도록 설정한 상태에서 코드를 실행한 다음 결과가 제한과 일치하는지 확인할 수 있습니다.(크레딧은 사용자 284130 :)

유의해야 할 중요한 사항:

  1. 사용하는 이미지는 적절히 최적화 및 압축되어야 합니다.그렇지 않으면 웹 서버에 의한 연결의 기본 압축이 실제보다 더 큰 속도를 나타낼 수 있습니다.다른 옵션은 압축할 수 없는 파일 형식을 사용하는 것입니다(예: jpg).

  2. 위에서 설명한 캐시 버스터 메커니즘은 일부 CDN 서버에서는 작동하지 않을 수 있습니다.CDN 서버에서는 쿼리 문자열 파라미터를 무시하도록 설정할 수 있으므로 이미지 자체에 캐시 제어 헤더를 설정하는 것이 좋습니다.(thanks orcaman for pointing this out)

  3. 이미지 크기가 클수록 좋습니다.이미지가 클수록 테스트의 정확도가 높아져 5MB도 괜찮지만 더 큰 이미지를 사용할 수 있다면 더 좋습니다.

지금은 2017년이므로 Network Information API(현재는 브라우저 전체에서 제한적으로 지원되지만)를 사용하여 다운링크 속도 추정 정보를 얻을 수 있습니다.

navigator.connection.downlink

이는 유효 대역폭 추정치(Mbits/sec)브라우저는 최근에 관찰된 애플리케이션 층의 스루풋을 통해 최근 활성 연결에서 이 값을 계산합니다.말할 필요도 없이 이 접근법의 가장 큰 장점은 대역폭/속도 계산만으로 콘텐츠를 다운로드할 필요가 없다는 것입니다.

이 Atribute와 기타 관련 Atribute를 여기서 확인할 수 있습니다.

한정된 지원과 브라우저 간의 구현이 다르기 때문에(2017년 11월 현재) 자세한 내용을 읽어보실 것을 강력히 권장합니다.

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

이 StackOverflow의 다른 답변에서 개략적으로 설명한 바와 같이 다양한 크기의 파일 다운로드 타이밍(접속이 허용하는 경우 작게 시작하여 확장)을 설정하여 캐시 헤더를 통해 파일이 실제로 캐시 서버에서 읽혀지고 캐시에서 검색되지 않도록 합니다.이 경우 반드시 자체 서버를 보유할 필요는 없지만(S3 또는 유사한 파일일 수 있음), 연결 속도를 테스트하기 위해서는 파일을 가져올 수 있는 장소가 필요합니다.

즉, 포인트 인 타임 대역폭 테스트는 다른 창에서 다운로드되는 다른 항목, 서버의 속도, 전송 중인 링크 등의 영향을 받기 때문에 신뢰할 수 없는 것으로 알려져 있습니다.하지만 이런 기술을 사용하면 대략적인 생각을 할 수 있습니다.

비록 이것이 오래되고 답변이 되었지만, 나는 그림자 마법사에서 말하는 더 이상의 전쟁은 없다'의 해결책을 바탕으로 2020년에 내가 만든 해결책을 공유하고 싶다.

지정된 mbps가 더 높거나 더 낮으면 언제든지 실행할 수 있고 콜백을 실행할 수 있는 유연성이 있는 객체에 병합했습니다.

testConnectionSpeed 오브젝트를 포함하면 어디서든 테스트를 시작할 수 있습니다.

/**
* @param float    mbps
* @param function morefunction/lessfunction(float result_mbps)
*/

testConnectionSpeed.run(mbps, morefunction, lessfunction)

예를 들어 다음과 같습니다.

var testConnectionSpeed = {
  imageAddr : "https://upload.wikimedia.org/wikipedia/commons/a/a6/Brandenburger_Tor_abends.jpg", // this is just an example, you rather want an image hosted on your server
  downloadSize : 2707459, // Must match the file above (from your server ideally)
  run:function(mbps_max,cb_gt,cb_lt){
    testConnectionSpeed.mbps_max = parseFloat(mbps_max) ? parseFloat(mbps_max) : 0;
    testConnectionSpeed.cb_gt = cb_gt;
    testConnectionSpeed.cb_lt = cb_lt;
    testConnectionSpeed.InitiateSpeedDetection();
  },
  InitiateSpeedDetection: function() {
    window.setTimeout(testConnectionSpeed.MeasureConnectionSpeed, 1);
  },
  result:function(){
    var duration = (endTime - startTime) / 1000;
    var bitsLoaded = testConnectionSpeed.downloadSize * 8;
    var speedBps = (bitsLoaded / duration).toFixed(2);
    var speedKbps = (speedBps / 1024).toFixed(2);
    var speedMbps = (speedKbps / 1024).toFixed(2);
    if(speedMbps >= (testConnectionSpeed.max_mbps ? testConnectionSpeed.max_mbps : 1) ){
      testConnectionSpeed.cb_gt ? testConnectionSpeed.cb_gt(speedMbps) : false;
    }else {
      testConnectionSpeed.cb_lt ? testConnectionSpeed.cb_lt(speedMbps) : false;
    }
  },
  MeasureConnectionSpeed:function() {
    var download = new Image();
    download.onload = function () {
        endTime = (new Date()).getTime();
        testConnectionSpeed.result();
    }
    startTime = (new Date()).getTime();
    var cacheBuster = "?nnn=" + startTime;
    download.src = testConnectionSpeed.imageAddr + cacheBuster;
  }
}




// start test immediatly, you could also call this on any event or whenever you want
testConnectionSpeed.run(1.5, function(mbps){console.log(">= 1.5Mbps ("+mbps+"Mbps)")}, function(mbps){console.log("< 1.5Mbps("+mbps+"Mbps)")} )

저속 인터넷 접속을 위해 로우 해상도 미디어를 로드하는 데 성공했습니다.이미지가 클수록 테스트가 합리적이고 접속이 느릴 경우 테스트에 시간이 오래 걸리기 때문에 특히 접속 속도가 느린 사용자가 많은 MB를 로드하는 것을 원하지 않기 때문에 조금 놀아야 합니다.

이미지 트릭은 훌륭하지만 테스트에서는 완료하고 싶은 Ajax 콜 전에 로딩되어 있었습니다.

2017년 적절한 해결책은 worker(http://caniuse.com/#webworkers=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 파일:

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

이것은, 10 MB 미만의 파일에서는 잘 동작하지 않습니다.여러 번의 다운로드 시도에서 집계 결과를 실행해야 합니다.

Punit S 응답 덕분에 동적 연결 속도 변화를 검출하기 위해 다음 코드를 사용할 수 있습니다.

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

John Smith의 답변을 개선하여 약속을 반환하고 다음과 같이 사용할 수 있는 훌륭하고 깨끗한 솔루션async/awaitMbps 단위의 값을 반환합니다.

const imageAddr = 'https://upload.wikimedia.org/wikipedia/commons/a/a6/Brandenburger_Tor_abends.jpg';
const downloadSize = 2707459; // this must match with the image above

let startTime, endTime;
async function measureConnectionSpeed() {
  startTime = (new Date()).getTime();
  const cacheBuster = '?nnn=' + startTime;

  const download = new Image();
  download.src = imageAddr + cacheBuster;
  // this returns when the image is finished downloading
  await download.decode();
  endTime = (new Date()).getTime();
  const duration = (endTime - startTime) / 1000;
  const bitsLoaded = downloadSize * 8;
  const speedBps = (bitsLoaded / duration).toFixed(2);
  const speedKbps = (speedBps / 1024).toFixed(2);
  const speedMbps = (speedKbps / 1024).toFixed(2);
  return Math.round(Number(speedMbps));
}

비슷한 게 필요해서 https://github.com/beradrian/jsbandwidth이라고 썼어요.이것은 https://code.google.com/p/jsbandwidth/의 개서입니다.

아이디어는 Ajax를 통해 2개의 콜을 발신하는 것입니다.하나는 다운로드하는 콜이고 다른 하나는 POST를 통해 업로드하는 것입니다.

양쪽에서 동작합니다.jQuery.ajax또는 각도$http.

//JUST AN EXAMPLE, PLEASE USE YOUR OWN PICTURE!
var imageAddr = "https://i.ibb.co/sPbbkkZ/pexels-lisa-1540258.jpg"; 
var downloadSize = 10500000; //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>

미니 스니펫:

var speedtest = {};
function speedTest_start(name) { speedtest[name]= +new Date(); }
function speedTest_stop(name) { return +new Date() - speedtest[name] + (delete 
speedtest[name]?0:0); }

다음과 같이 사용:

speedTest_start("test1");

// ... some code

speedTest_stop("test1");
// returns the time duration in ms

또한 더 많은 테스트를 수행할 수 있습니다.

speedTest_start("whole");

// ... some code

speedTest_start("part");

// ... some code

speedTest_stop("part");
// returns the time duration in ms of "part"

// ... some code

speedTest_stop("whole");
// returns the time duration in ms of "whole"

언급URL : https://stackoverflow.com/questions/5529718/how-to-detect-internet-speed-in-javascript

반응형