¿Cómo puedo crear una página de JavaScript que detecte la velocidad de Internet del usuario y la muestre en la página? Algo así como "su velocidad de internet es ?? / ?? Kb / s " .
¿Cómo puedo crear una página de JavaScript que detecte la velocidad de Internet del usuario y la muestre en la página? Algo así como "su velocidad de internet es ?? / ?? Kb / s " .
Respuestas:
Es posible hasta cierto punto, pero no será realmente preciso, la idea es cargar la imagen con un tamaño de archivo conocido y, en su onload
caso, medir cuánto tiempo pasó hasta que se activó ese evento y dividir este tiempo en el tamaño del archivo de imagen.
El ejemplo se puede encontrar aquí: calcular la velocidad usando javascript
Caso de prueba aplicando la solución sugerida allí:
//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>
La comparación rápida con el servicio de prueba de velocidad "real" mostró una pequeña diferencia de 0,12 Mbps cuando se usa una imagen general.
Para garantizar la integridad de la prueba, puede ejecutar el código con la limitación de la herramienta de desarrollo de Chrome habilitada y luego ver si el resultado coincide con la limitación. (el crédito va al usuario284130 :))
Cosas importantes a tener en cuenta:
La imagen que se usa debe estar correctamente optimizada y comprimida. Si no es así, la compresión predeterminada en las conexiones del servidor web puede mostrar una velocidad mayor de lo que realmente es. Otra opción es utilizar un formato de archivo no comprimible, por ejemplo, jpg. (gracias Rauli Rajande por señalar esto y Fluxine por recordármelo )
El mecanismo de bloqueo de caché descrito anteriormente podría no funcionar con algunos servidores CDN, que pueden configurarse para ignorar los parámetros de la cadena de consulta, por lo tanto, es mejor configurar los encabezados de control de caché en la imagen misma. (gracias orcaman por señalar esto ) )
Bueno, esto es 2017, por lo que ahora tiene API de información de red (aunque con un soporte limitado en todos los navegadores a partir de ahora) para obtener algún tipo de información estimada de velocidad de enlace descendente:
navigator.connection.downlink
Esta es una estimación efectiva del ancho de banda en Mbits por segundo. El navegador realiza esta estimación a partir del rendimiento de la capa de aplicación recientemente observado a través de conexiones activas recientemente. No es necesario decir que la mayor ventaja de este enfoque es que no necesita descargar ningún contenido solo para calcular el ancho de banda / velocidad.
Puedes ver esto y otros atributos relacionados aquí
Debido a su soporte limitado y diferentes implementaciones en todos los navegadores (a partir de noviembre de 2017), recomendaría leer esto en detalle
Como describo en esta otra respuesta aquí en StackOverflow , puede hacerlo cronometrando la descarga de archivos de varios tamaños (comience con poco, aumente si la conexión parece permitirlo), asegurándose a través de los encabezados de caché y tal que el archivo sea realmente se lee desde el servidor remoto y no se recupera de la memoria caché. Esto no requiere necesariamente que tenga un servidor propio (los archivos podrían provenir de S3 o similar), pero necesitará un lugar desde donde obtener los archivos para probar la velocidad de conexión.
Dicho esto, las pruebas de ancho de banda en un punto en el tiempo son notoriamente poco confiables, ya que se ven afectadas por otros elementos que se descargan en otras ventanas, la velocidad de su servidor, enlaces en ruta, etc., etc. Pero puede tener una idea aproximada usando este tipo de técnica.
iframe
, por ejemplo, sondea el iframe
o una cookie para completar. Si usa un XMLHttpRequest
objeto para hacer la publicación, hay una devolución de llamada para completar.
Necesitaba una forma rápida de determinar si la velocidad de conexión del usuario era lo suficientemente rápida como para habilitar / deshabilitar algunas funciones en un sitio en el que estoy trabajando, hice este pequeño script que promedia el tiempo que toma descargar una sola imagen (pequeña) varias veces, funciona con bastante precisión en mis pruebas, pudiendo distinguir claramente entre 3G o Wi-Fi, por ejemplo, tal vez alguien pueda hacer una versión más elegante o incluso un complemento 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);
}
}
El truco de la imagen es genial, pero en mis pruebas se estaba cargando antes de algunas llamadas ajax que quería completar.
La solución adecuada en 2017 es utilizar un trabajador ( http://caniuse.com/#feat=webworkers ).
El trabajador se verá así:
/**
* 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
);
};
El archivo js que invocará al trabajador:
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);
}
};
Código tomado de un paquete de Plone que escribí:
Es mejor usar imágenes para probar la velocidad. Pero si tiene que lidiar con archivos zip, el siguiente código funciona.
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();
Esto no funcionará muy bien con archivos <10 MB. Tendrá que ejecutar resultados agregados en múltiples intentos de descarga.
Necesitaba algo similar, así que escribí https://github.com/beradrian/jsbandwidth . Esta es una reescritura de https://code.google.com/p/jsbandwidth/ .
La idea es hacer dos llamadas a través de Ajax, una para descargar y la otra para cargar a través de POST.
Debería funcionar con ambos jQuery.ajax
o Angular $http
.
Gracias a la respuesta de Punit S, para detectar el cambio dinámico de la velocidad de conexión, puede usar el siguiente código:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}