JS 檢測網路頻寬

王玉略發表於2018-07-17

最近專案上有需求要檢測網路的頻寬,網上找了不少解決方案,以下王二來做一個整理

1、方法一

第一種思路是 載入一張圖片,通過的載入時長和圖片的大小來計算出網路頻寬

有了這個思路,我們可以參考如下程式碼(部分參考自 github 上的debloper/bandwidth.js):

function measureBW(fn) {
    var startTime, endTime, fileSize;

    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = () => {
        if(xhr.readyState === 2){
            startTime = Date.now();
        }
        if (xhr.readyState === 4 && xhr.status === 200) {
            endTime = Date.now();
            fileSize = xhr.responseText.length;
            var speed = fileSize  / ((endTime - startTime)/1000) / 1024;
            fn && fn(Math.floor(speed))
        }
    }

    xhr.open("GET", "https://upload.wikimedia.org/wikipedia/commons/5/51/Google.png", true);
    xhr.send();
}

measureBW((speed)=>{
    console.log(speed + " KB/sec");  //215 KB/sec
})
複製程式碼

2、方法二

但是考慮到http請求需要建立連線,以及等待響應,這些過程也會消耗一些時間,所以以上的方法可能不會準確的檢測出網路頻寬。

我們可以同時發出多次請求,來減少http請求建立連線,等待響應的影響,參考如下程式碼:

function measureBW(fn,time) {
    time = time || 1;
    var startTime, endTime, fileSize;
    var count = time ;
    var _this = this;
    function measureBWSimple () {
        
        var xhr = new XMLHttpRequest();

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4 && xhr.status === 200) {
                if(!fileSize){
                    fileSize = xhr.responseText.length;
                }
                count --;
                if(count<=0){
                    endTime = Date.now();
                    var speed = fileSize * time  / ((endTime - startTime)/1000) / 1024;
                    fn && fn(Math.floor(speed));
                }
            }
        }
        xhr.open("GET", "https://upload.wikimedia.org/wikipedia/commons/5/51/Google.png", true);
        xhr.send();
    }
    startTime = Date.now();
    for(var x = time;x>0;x--){
        measureBWSimple()
    }
}

measureBW((speed)=>{
    console.log(speed + " KB/sec");  //913 KB/sec
},10)
複製程式碼

經王二測試,第二種方法得到的結果要比方法一得到的結果明顯高出不少。

事實上,前兩種還要額外設定 http 請求頭來禁止使用本地快取(開發測試下可以在控制檯Network皮膚下點選禁用快取),要不然圖片載入一次後就不會在去伺服器載入,自然也測不出網路的頻寬.

3、方法三

Chrome65+ 的版本中,新增了一些原生的方法可以檢測有關裝置正在使用的連線與網路進行通訊的資訊。

參考如下程式碼,我們就可以檢測到網路頻寬:

function measureBW () {
    return navigator.connection.downlink;
}
measureBW() ;
複製程式碼

navigator.connection.downlink 會返回以(兆位元/秒)為單位的有效頻寬估計值(參考MDN),這和我們常用的(KB/sec)有所差別,所以我們需要再做一下單位換算,參考如下程式碼:

function measureBW () {
    return navigator.connection.downlink * 1024 /8;   //單位為KB/sec
}
measureBW() ;
複製程式碼

我們還可以通過 navigator.connection 上的 change 事件來監聽網路頻寬的變化:

navigator.connection.addEventListener('change', measureBW());
複製程式碼

參考文章:

MDN NetworkInformation

Network Information API Sample

Kbps、KB、Mbps單位換算

原文地址:

王玉略的個人網站

相關文章