Using the Pace.js plugin as the basis (https://github.com/HubSpot/pace), it uses several methods to detect page load percentage:
Ajax requests:
- The plugin checks the requests by calculating the percentage of each one depending on its type:
If the request is an Xmlhttprequest it uses the "Progress" event, which returns an object with the file size being downloaded and when it has been completed, if Content-Length is available in the Response request header. In addition to also checking the events "load", "abort", "timeout" and "error" to determine whether the request has ended.
request.addEventListener('progress', function(evt) {
//Verifica se Content-Length foi declarado no Header de resposta
if (evt.lengthComputable) {
//Calcula a porcentagem de acordo com o quanto já foi baixado.
return _this.progress = 100 * evt.loaded / evt.total;
} else {
//Se não há Content-Length retorna uma porcentagem sintética.
return _this.progress = _this.progress + (100 - _this.progress) / 2;
}
}, false);
If the request type is a Websocket it checks the "error" and "open" events to determine if the request has ended.
SocketRequestTracker = (function() {
function SocketRequestTracker(request) {
var event, _j, _len1, _ref2,
_this = this;
this.progress = 0;
_ref2 = ['error', 'open'];
//Registra listener aos eventos acima para determinar quando conexão estiver estabelecida, ou não.
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
event = _ref2[_j];
request.addEventListener(event, function() {
return _this.progress = 100;
}, false);
}
}
return SocketRequestTracker;
})();
HTML document:
- The plugin uses the Document.readystate to determine the state the document is in ("loading", "Interactive", "complete") and assigns a percentage to each.
DocumentMonitor = (function() {
//Determina porcentagens para cada estado de document.readyState.
DocumentMonitor.prototype.states = {
loading: 0,
interactive: 50,
complete: 100
};
function DocumentMonitor() {
var _onreadystatechange, _ref2,
_this = this;
//Verifica document.readystate e atribui valor ao estado atual da página
this.progress = (_ref2 = this.states[document.readyState]) != null ? _ref2 : 100;
_onreadystatechange = document.onreadystatechange;
//Nas mudanças de estado atualiza o valor da porcentagem
document.onreadystatechange = function() {
if (_this.states[document.readyState] != null) {
_this.progress = _this.states[document.readyState];
}
return typeof _onreadystatechange === "function" ? _onreadystatechange.apply(null, arguments) : void 0;
};
}
return DocumentMonitor;
})();
Lag in the Loop of Events:
- The plugin checks by lag in the event loop whether there is javascript code running and calculates a lag percentage.
EventLagMonitor = (function() {
function EventLagMonitor() {
var avg, interval, last, points, samples,
_this = this;
this.progress = 0;
avg = 0;
samples = [];
points = 0;
last = now();
//Utiliza um timer para calcular o Lag no loop de eventos do javascript
interval = setInterval(function() {
var diff;
//Calcula a diferença entre o tempo de execução determinado para o Timer (50ms) e o tempo real de execução
diff = now() - last - 50;
last = now();
samples.push(diff);
if (samples.length > options.eventLag.sampleCount) {
samples.shift();
}
//Calcula a amplitude media a partir dos Lag's salvos
avg = avgAmplitude(samples);
//Verifica se a amplitude dos Lag's está acima do limite na execução do javascript
if (++points >= options.eventLag.minSamples && avg < options.eventLag.lagThreshold) {
_this.progress = 100;
return clearInterval(interval);
} else {
//Se estiver, calcula a porcentagem a partir dessa amplitude.
return _this.progress = 100 * (3 / (avg + 3));
}
}, 50);
}
return EventLagMonitor;
})();
HTML elements (optional):
- The plugin checks the existence of certain predetermined elements using the Document.querySelector.
//De acordo com a documentação - Define as classes/id's a serem verificados pelo pace.js
paceOptions = {
elements: {
selectors: ['.timeline,.timeline-error', '.user-profile,.profile-error']
}
}
//Para verificar a existência dos elementos no documento
ElementTracker = (function() {
function ElementTracker(selector) {
this.selector = selector;
this.progress = 0;
this.check();
}
ElementTracker.prototype.check = function() {
var _this = this;
if (document.querySelector(this.selector)) {
return this.done();
} else {
return setTimeout((function() {
return _this.check();
}), options.elements.checkInterval);
}
};
ElementTracker.prototype.done = function() {
return this.progress = 100;
};
return ElementTracker;
})();
in this case, the request to the server is a data download? or some intensive routine?
– Tobias Mesquita
http://github.hubspot.com/pace/docs/welcome/ If you access this page, you will see that the jQuery plugin somehow detects the page load progress and represents it graphically. That’s what I want to know How it works....
– Pedro Vinícius
it is possible to do with
XMLHttpRequest.addEventListener("progress", function, false)
, but the page needs to expose your work in Header through the propertyContent-Length
.– Tobias Mesquita
Interesting what you said @Tobymosque. I’ll read more about it...
– Pedro Vinícius