Based on the pace.js plugin ( link ), it uses a number of methods to detect the page load percentage:
Ajax requests:
- The plugin checks the requests, 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 size of the file being downloaded and how long it has been completed, if Content-Length is available in the Response Request Header. In addition to checking the events "load", "abort", "timeout" and "error" to determine if the request is over.
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 is terminated.
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 document.readystate to determine the state the document is in ("loading", "interactive", "complete") and assigns a percentage for 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 Event Loop:
- The plugin checks through the lag in the event loop if javascript code is running and calculates a percentage relative to lag.
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 for certain default elements using 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;
})();