前端监控系统 目前已经上线,欢迎使用!
随着前端项目的权重不断加大,前后端分离也变得越来越有必要。前端项目开始承担着更多的功能和责任,所以前端性能的优化就变得很重要了。
对于一个前后端分离的前端项目,接口获取数据是必不可少的,所以接口的优化直接关系到用户体验的问题,那么,我们怎么知道线上项目的接口状态是否良好呢?
一、如何去判断页面上接口请求的质量
对于一个html页面, 发出最少的请求,每个接口请求消耗最短的时间为最佳
- 因为用户远在千里之外,页面上每发一个请求的代价都是巨大的,代价越高,风险就会越高,当一个接口请求发生了一系列的不利的结果将直接导致用户体验差,这是我们前端工程师所不能够接受的。而且对于高并发的前端项目来说,过多的接口请求,对服务器造成的压力也是不容小觑的,所以我们要尽量减少一个页面上的请求数量。
- 接口耗时是影响用户体验的一个重要因素,用户从某个动作开始发出请求,到得到相应的反馈结果,这个时间段不可以太长,否则用户会以为程序死掉,或者直接放弃。
以上图为例,所有的接口请求耗时都是毫秒级别,而且浮动不大,比较稳定,我们可以视为优良。 但是第二个表中展示,平均每个页面发出的请求次数居然有达到14次之多,这就是需要优化的地方了
二、分析页面上的ajax请求方式
如我们所知,比较常用的ajax请求方式有,jquery分装的ajax方法,目前正在流行的fetch方法,或者直接调用XMLHttpRequest来发送请求。 虽然方式有三种,但是我们可以看看jquery.ajax() 和 fetch的源码
Jquery.ajax 源码:
// Functions to create xhrs
function createStandardXHR() {
try {
return new window.XMLHttpRequest();
} catch( e ) {}
}
function createActiveXHR() {
try {
return new window.ActiveXObject( "Microsoft.XMLHTTP" );
} catch( e ) {}
}
// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
/* Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
* so we use the ActiveXObject when it is available
* Additionally XMLHttpRequest can be disabled in IE7/IE8 so
* we need a fallback.
*/
function() {
return !this.isLocal && createStandardXHR() || createActiveXHR();
} :
// For all other browsers, use the standard XMLHttpRequest object
createStandardXHR;
fetch 源码:
self.fetch = function(input, init) {
fetchHttpUrl = input;
return new Promise(function(resolve, reject) {
var request = new Request(input, init)
var xhr = new XMLHttpRequest()
xhr.onload = function() {
// ....
}
// ...
xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
})
}
其实不难看出, jquery的ajax, fetch方法都是通过 new XMLHttpRequest() 创建了一个XMLHttpRequest的对象,然后做了一系列的异步请求操作。
既然清楚这一点了,那么我们监控页面上的请求,就会简单很多了。
三、如何去监控页面上发出的请求呢?
根据第一点,我们需要分析的是,接口的平均请求耗时,和每个页面的请求频次。那么就需要记录下接口的请求次数,和每个接口的请求时间
先看一段代码:
function ajaxEventTrigger(event) {
var ajaxEvent = new CustomEvent(event, {
detail: this
});
window.dispatchEvent(ajaxEvent);
}
var oldXHR = window.XMLHttpRequest;
function newXHR() {
var realXHR = new oldXHR();
realXHR.addEventListener('abort', function () { ajaxEventTrigger.call(this, 'ajaxAbort'); }, false);
realXHR.addEventListener('error', function () { ajaxEventTrigger.call(this, 'ajaxError'); }, false);
realXHR.addEventListener('load', function () { ajaxEventTrigger.call(this, 'ajaxLoad'); }, false);
realXHR.addEventListener('loadstart', function () { ajaxEventTrigger.call(this, 'ajaxLoadStart'); }, false);
realXHR.addEventListener('progress', function () { ajaxEventTrigger.call(this, 'ajaxProgress'); }, false);
realXHR.addEventListener('timeout', function () { ajaxEventTrigger.call(this, 'ajaxTimeout'); }, false);
realXHR.addEventListener('loadend', function () { ajaxEventTrigger.call(this, 'ajaxLoadEnd'); }, false);
realXHR.addEventListener('readystatechange', function() { ajaxEventTrigger.call(this, 'ajaxReadyStateChange'); }, false);
return realXHR;
}
window.addEventListener('ajaxLoadEnd', function(e) {
// 记录日志的逻辑
});
window.addEventListener('ajaxError', function(e) {
});
数据库字段设计如下:
OK, 接口请求统计完成了。
