How to detect internet speed in JavaScript?

前端 未结 9 1419
萌比男神i
萌比男神i 2020-11-22 01:56

How can I create a JavaScript page that will detect the user’s internet speed and show it on the page? Something like “your internet speed is ??/?? Kb/s”.

相关标签:
9条回答
  • 2020-11-22 02:33

    I needed a quick way to determine if the user connection speed was fast enough to enable/disable some features in a site I’m working on, I made this little script that averages the time it takes to download a single (small) image a number of times, it's working pretty accurately in my tests, being able to clearly distinguish between 3G or Wi-Fi for example, maybe someone can make a more elegant version or even a jQuery plugin.

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

    0 讨论(0)
  • 2020-11-22 02:39

    The image trick is cool but in my tests it was loading before some ajax calls I wanted to be complete.

    The proper solution in 2017 is to use a worker (http://caniuse.com/#feat=webworkers).

    The worker will look like:

    /**
     * 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
      );
    };
    

    The js file that will invoke the Worker:

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

    Code taken from a Plone package I wrote:

    • https://github.com/collective/experimental.bwtools/blob/master/src/experimental/bwtools/browser/static/scripts/
    0 讨论(0)
  • 2020-11-22 02:40

    I needed something similar, so I wrote https://github.com/beradrian/jsbandwidth. This is a rewrite of https://code.google.com/p/jsbandwidth/.

    The idea is to make two calls through Ajax, one to download and the other to upload through POST.

    It should work with both jQuery.ajax or Angular $http.

    0 讨论(0)
  • 2020-11-22 02:45

    thanks to Punit S answer, for detecting dynamic connection speed change, you can use the following code :

    navigator.connection.onchange = function () {
     //do what you need to do ,on speed change event
     console.log('Connection Speed Changed');
    }
    
    0 讨论(0)
  • 2020-11-22 02:49

    It's possible to some extent but won't be really accurate, the idea is load image with a known file size then in its onload event measure how much time passed until that event was triggered, and divide this time in the image file size.

    Example can be found here: Calculate speed using javascript

    Test case applying the fix suggested there:

    //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>

    Quick comparison with "real" speed test service showed small difference of 0.12 Mbps when using big picture.

    To ensure the integrity of the test, you can run the code with Chrome dev tool throttling enabled and then see if the result matches the limitation. (credit goes to user284130 :))

    Important things to keep in mind:

    1. The image being used should be properly optimized and compressed. If it isn't, then default compression on connections by the web server might show speed bigger than it actually is. Another option is using uncompressible file format, e.g. jpg. (thanks Rauli Rajande for pointing this out and Fluxine for reminding me)

    2. The cache buster mechanism described above might not work with some CDN servers, which can be configured to ignore query string parameters, hence better setting cache control headers on the image itself. (thanks orcaman for pointing this out))

    0 讨论(0)
  • 2020-11-22 02:49

    Well, this is 2017 so you now have Network Information API (albeit with a limited support across browsers as of now) to get some sort of estimate downlink speed information:

    navigator.connection.downlink
    

    This is effective bandwidth estimate in Mbits per sec. The browser makes this estimate from recently observed application layer throughput across recently active connections. Needless to say, the biggest advantage of this approach is that you need not download any content just for bandwidth/ speed calculation.

    You can look at this and a couple of other related attributes here

    Due to it's limited support and different implementations across browsers (as of Nov 2017), would strongly recommend read this in detail

    0 讨论(0)
提交回复
热议问题