detect slow network javascript
¿Cómo detectar la velocidad de internet en JavaScript? (8)
Bueno, esto es 2017, así que ahora tienes la API de información de red (aunque con un soporte limitado en los navegadores a partir de ahora) para obtener algún tipo de información de velocidad de enlace descendente:
navigator.connection.downlink
Esta es una estimación de ancho de banda efectiva en Mbits por segundo. El navegador realiza esta estimación a partir del rendimiento de la capa de aplicaciones observado recientemente en las conexiones activas recientes. Huelga decir que la mayor ventaja de este enfoque es que no necesita descargar ningún contenido solo para el cálculo del ancho de banda / velocidad.
Puedes ver este y un par de atributos relacionados here
Debido a su soporte limitado y las diferentes implementaciones en los navegadores (a partir de noviembre de 2017), recomendamos leer this en detalle
¿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 como "tu velocidad de internet es ?? / ?? Kb / s " .
Como lo describo en esta otra respuesta aquí en , puedes hacer esto al sincronizar la descarga de archivos de varios tamaños (comenzar de a poco, aumentar si la conexión parece permitir), asegurar a través de los encabezados de caché y 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 pueden provenir de S3 o similar), pero necesitará algún lugar para obtener los archivos para probar la velocidad de conexión.
Dicho esto, las pruebas de ancho de banda puntuales son notoriamente poco confiables, ya que se ven afectadas por otros elementos que se descargan en otras ventanas, la velocidad de su servidor, los enlaces en ruta, etc., etc. Pero puede obtener una idea aproximada usando este tipo de técnica.
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 tratar 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 <10MB. 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 tanto con jQuery.ajax
como con Angular $http
.
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 lleva descargar una única imagen (pequeña) varias veces, funciona con bastante precisión en mis pruebas, y puedo distinguir claramente entre 3G o Wi-Fi, por ejemplo, tal vez alguien puede 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);
}
}
Puede determinar el tiempo de carga de la página. Intente utilizar el siguiente script para medir el tiempo que lleva cargar una página por completo:
<html>
<head>
<script type="text/javascript">
var start = new Date().getTime();
function onLoad() {
var now = new Date().getTime();
var latency = now - start;
alert("page loading time: " + latency);
}
</script>
</head>
<body onload="onLoad()">
<!- Main page body goes from here. -->
</body>
</html>
Vea la página de 3WC sobre el tiempo de navegación:
https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
Es posible hasta cierto punto, pero no será realmente preciso, la idea es cargar imágenes con un tamaño de archivo conocido y luego en su evento de carga medir cuánto tiempo pasó hasta que se desencadenó ese evento, y dividir este tiempo en el tamaño del archivo de imagen.
El ejemplo se puede encontrar aquí: Calcula 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 grande.
Para garantizar la integridad de la prueba, puede ejecutar el código con la aceleració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 user284130 :))
Cosas importantes a tener en cuenta:
La imagen que se utiliza debe optimizarse y comprimirse adecuadamente. Si no es así, la compresión predeterminada en las conexiones del servidor web podría mostrar una velocidad mayor de lo que realmente es. Otra opción es usar un formato de archivo incompresible, por ejemplo, jpg. (Gracias Rauli Rajande por señalar esto y Fluxine por recordarme )
El mecanismo de destrucción de caché descrito anteriormente podría no funcionar con algunos servidores CDN, que pueden configurarse para ignorar los parámetros de cadena de consulta, por lo tanto, es mejor establecer los encabezados de control de caché en la propia imagen. (gracias orcaman por señalar esto ) )