262
4

12 に答える 12

339

ある程度は可能ですが、実際には正確ではありません。アイデアは、既知のファイルサイズで画像を読み込み、そのイベントでその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開発ツールのスロットリングを有効にしてコードを実行し、結果が制限に一致するかどうかを確認できます。(クレジットはuser284130に送られます:))

覚えておくべき重要なこと:

  1. 使用する画像は、適切に最適化および圧縮する必要があります。そうでない場合、Webサーバーによる接続のデフォルトの圧縮は、実際よりも速い速度を示す可能性があります。もう1つのオプションは、jpgなどの非圧縮ファイル形式を使用することです。(これを指摘してくれたRauli Rajandeと私に思い出させてくれたFluxineに感謝します)

  2. 上記のキャッシュバスターメカニズムは、クエリ文字列パラメーターを無視するように構成できる一部のCDNサーバーでは機能しない可能性があるため、イメージ自体にキャッシュ制御ヘッダーを設定する方が適切です。(これを指摘してくれたorcamanに感謝します)

  3. 画像サイズが大きいほど良いです。画像が大きいほどテストはより正確になり、5 mbは適切ですが、さらに大きな画像を使用できる場合はそれが良いでしょう。

于 2011-04-03T13:25:02.537 に答える
26

私が取り組んでいるサイトの一部の機能を有効/無効にするのに十分な速度でユーザーの接続速度が速かったかどうかを簡単に判断する方法が必要でした。多くの場合、私のテストではかなり正確に機能しており、たとえば 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);
  }
}

于 2014-01-27T02:38:36.353 に答える
23

ここの StackOverflow に関するこの他の回答で概説しているように、さまざまなサイズのファイルのダウンロードのタイミングを調整することでこれを行うことができます (小さく始めて、接続が許可されている場合はランプアップします)。キャッシュ ヘッダーなどを通じて、ファイルが実際にリモートサーバーから読み取られ、キャッシュから取得されていません。これは必ずしも独自のサーバーを持っている必要はありません (ファイルはS3などから来ている可能性があります) が、接続速度をテストするためにファイルを取得する場所が必要になります。

とはいえ、ポイントインタイム帯域幅テストは、他のウィンドウでダウンロードされている他のアイテム、サーバーの速度、途中のリンクなどの影響を受けるため、信頼できないことで有名です.しかし、大まかなアイデアを得ることができます.こういうテクニックを使って。

于 2011-04-03T13:13:02.877 に答える