ユーザーのインターネット速度を検出してページに表示するJavaScriptページを作成するにはどうすればよいですか?何かのように「あなたのインターネットの速度は?? / ??です Kb / s」。
ユーザーのインターネット速度を検出してページに表示する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.12 Mbpsの小さな違いが示されました。
テストの整合性を確保するには、Chrome開発ツールのスロットルを有効にしてコードを実行し、結果が制限と一致するかどうかを確認します。(クレジットはuser284130に送られます :))
覚えておくべき重要なこと:
さて、これは2017年ですので、ネットワーク情報API(現在のところ、ブラウザー全体でサポートが制限されています)を使用して、何らかの推定ダウンリンク速度情報を取得できます。
navigator.connection.downlink
これは、1秒あたりのMbitsでの有効な帯域幅の見積もりです。ブラウザーは、最近アクティブな接続全体で最近観測されたアプリケーションレイヤーのスループットからこの推定を行います。言うまでもなく、このアプローチの最大の利点は、帯域幅/速度の計算のためだけにコンテンツをダウンロードする必要がないことです。
これと他のいくつかの関連属性をここで見ることができます
(2017年11月の時点で)ブラウザー間でサポートが制限され、実装が異なるため、これを詳細に読むことを強くお勧めします
StackOverflowでこの他の回答の概要を説明しているように、さまざまなサイズのファイルのダウンロードのタイミングを調整することで、接続を許可していると思われる場合は、小さいサイズから開始し、キャッシュヘッダーを介して、ファイルが本当にリモートサーバーから読み取られ、キャッシュから取得されていません。これは必ずしも独自のサーバーを持っている必要はありません(ファイルはS3または同様のものから来る可能性があります)が、接続速度をテストするためにファイルを取得する場所が必要になります。
とはいえ、ポイントインタイム帯域幅テストは、他のウィンドウでダウンロードされている他のアイテム、サーバーの速度、転送中のリンクなどの影響を受けるため、信頼性が低いことで悪名高く知られています。この種のテクニックを使用します。
iframe
を送信すると、iframe
またはCookieをポーリングして完了を確認します。XMLHttpRequest
オブジェクトを使用して投稿を行う場合、完了のためのコールバックがあります。
ユーザーの接続速度が、作業中のサイトで一部の機能を有効/無効にするのに十分な速さであるかどうかをすばやく判断する方法が必要でした。何度も、それは私のテストではかなり正確に機能しており、たとえば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);
}
}
画像のトリックはクールですが、私のテストでは、いくつかのajax呼び出しが完了する前にロードされていました。
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
);
};
ワーカーを呼び出す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を介して2つの呼び出しを行うことです。1つはダウンロード、もう1つはPOSTを介してアップロードします。
両方jQuery.ajax
またはAngularで動作するはず$http
です。
Punit Sの回答のおかげで、動的な接続速度の変化を検出するには、次のコードを使用できます。
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}