Como posso criar uma página JavaScript que detecta a velocidade da Internet do usuário e a mostra na página? Algo como "a velocidade da sua internet é ?? / ?? Kb / s ” .
Como posso criar uma página JavaScript que detecta a velocidade da Internet do usuário e a mostra na página? Algo como "a velocidade da sua internet é ?? / ?? Kb / s ” .
Respostas:
É possível, até certo ponto, mas não será realmente preciso, a ideia é carregar a imagem com um tamanho de arquivo conhecido e, em seu onload
evento, medir quanto tempo passou até que o evento foi acionado e dividir esse tempo no tamanho do arquivo de imagem.
Exemplo pode ser encontrado aqui: Calcular velocidade usando javascript
Caso de teste que aplica a correção sugerida aqui:
//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>
A comparação rápida com o serviço de teste de velocidade "real" mostrou uma pequena diferença de 0,12 Mbps ao usar imagem grande.
Para garantir a integridade do teste, você pode executar o código com a otimização da ferramenta de desenvolvimento do Chrome ativada e ver se o resultado corresponde à limitação. (o crédito vai para user284130 :))
Coisas importantes a ter em mente:
A imagem que está sendo usada deve ser adequadamente otimizada e compactada. Caso contrário, a compactação padrão nas conexões do servidor da web poderá mostrar uma velocidade maior do que realmente é. Outra opção é usar um formato de arquivo não compactável, por exemplo, jpg. (obrigado Rauli Rajande por apontar isso e Fluxine por me lembrar )
O mecanismo de buster de cache descrito acima pode não funcionar com alguns servidores CDN, que podem ser configurados para ignorar os parâmetros da string de consulta, portanto, definindo melhor os cabeçalhos de controle de cache na própria imagem. (obrigado orcaman por apontar isso ) )
Bem, como estamos em 2017, agora você tem a API de informações de rede (embora com um suporte limitado entre navegadores a partir de agora) para obter algum tipo de estimativa de informações de velocidade de downlink:
navigator.connection.downlink
Essa é uma estimativa de largura de banda efetiva em Mbits por segundo. O navegador faz essa estimativa a partir da taxa de transferência da camada de aplicativo observada recentemente em conexões ativas recentemente. Desnecessário dizer que a maior vantagem dessa abordagem é que você não precisa baixar nenhum conteúdo apenas para o cálculo da largura de banda / velocidade.
Você pode ver isso e outros atributos relacionados aqui
Devido ao seu suporte limitado e diferentes implementações nos navegadores (a partir de novembro de 2017), é altamente recomendável ler isso em detalhes
Como descrevi nesta outra resposta aqui no StackOverflow , você pode fazer isso cronometrando o download de arquivos de vários tamanhos (comece pequeno, aumente se a conexão parece permitir), garantindo através de cabeçalhos de cache e de forma que o arquivo seja realmente sendo lido do servidor remoto e não sendo recuperado do cache. Isso não requer necessariamente que você tenha um servidor próprio (os arquivos podem ser provenientes do S3 ou similar), mas você precisará de um local para obter os arquivos, a fim de testar a velocidade da conexão.
Dito isso, os testes de largura de banda point-in-time são notoriamente não confiáveis, pois são impactados por outros itens sendo baixados em outras janelas, a velocidade do seu servidor, links no caminho etc. etc. Mas você pode ter uma idéia aproximada usando esse tipo de técnica.
iframe
, por exemplo, você pesquisa o iframe
ou um cookie para conclusão. Se você usar um XMLHttpRequest
objeto para fazer a postagem, haverá um retorno de chamada para conclusão.
Eu precisava de uma maneira rápida de determinar se a velocidade de conexão do usuário era rápida o suficiente para ativar / desativar alguns recursos em um site em que estou trabalhando. Criei este pequeno script que calcula a média do tempo necessário para baixar uma única imagem (pequena) várias vezes, está funcionando com muita precisão nos meus testes, sendo capaz de distinguir claramente entre 3G ou Wi-Fi, por exemplo, talvez alguém possa criar uma versão mais elegante ou até mesmo um plugin 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);
}
}
O truque da imagem é legal, mas nos meus testes ele estava carregando antes de algumas chamadas do ajax que eu queria concluir.
A solução adequada em 2017 é usar um trabalhador ( http://caniuse.com/#feat=webworkers ).
O trabalhador terá a seguinte aparência:
/**
* 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
);
};
O arquivo js que chamará o 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);
}
};
Código retirado de um pacote Plone que escrevi:
É melhor usar imagens para testar a velocidade. Mas se você precisar lidar com arquivos zip, o código abaixo funcionará.
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();
Isso não funcionará muito bem com arquivos <10 MB. Você precisará executar resultados agregados em várias tentativas de download.
Eu precisava de algo semelhante, então escrevi https://github.com/beradrian/jsbandwidth . Esta é uma reescrita de https://code.google.com/p/jsbandwidth/ .
A idéia é fazer duas chamadas através do Ajax, uma para baixar e a outra para enviar pelo POST.
Deve funcionar com ambos jQuery.ajax
ou Angular $http
.
Graças à resposta Punit S, para detectar alterações dinâmicas na velocidade da conexão, você pode usar o seguinte código:
navigator.connection.onchange = function () {
//do what you need to do ,on speed change event
console.log('Connection Speed Changed');
}