所谓web,即便你我素未谋面,便知志趣相投;足不出户,亦知世界之大。git
如今的web应用,大都是经过请求(http)去获取资源,拿到资源后再呈现给用户,一个页面中能够有多个这样的请求。每一次请求的开始,等待,完成,异常都会有相应的状态来标识。咱们在本身的框架中一般都会使用一个全局过滤器,来拦截请求,目的大同小异:github
看看请求的整个流程图:web
而咱们最经常使用的发送请求的即是XMLHttpRequest。浏览器
XMLHttpRequest.readyState的五种就绪状态:服务器
而且XMLHttpRequest还提供了每一个阶段的事件:网络
若是请求停止,会触发abort事件。数据结构
网络错误(如太多重定向)会阻止请求完成,会触发error事件。app
当事件完成,会触发load事件。框架
当一个请求完成,不管成功(load)或者不成功(abort/error)后触发ide
当调用send()时,触发单个loadstart事件。
当等待服务器的响应时,XHR对象会发生progress事件。一般每隔50毫秒左右,因此可使用这事件给用户反馈请求的进度。
当等待服务器的响应超时会触发。
了解了XMLHttpRequest的请求流程后,咱们就能够开始去拦截浏览器发出的请求,去作咱们想作的事。
方式一:
(function (xhr) { // Capture request before any network activity occurs: var send = xhr.send; xhr.send = function (data) { this.addEventListener('loadstart', onLoadStart); this.addEventListener('loadend', onLoadEnd); this.addEventListener('error', onError); return send.apply(this, arguments); }; })(XMLHttpRequest.prototype);
这种是最简单直接的方式,修改XMLHttpRequest的原型,在发送请求时开启事件监听。大多数状况下都是没什么大问题的,但后来发如今Angular4+以上版本中这样去拦截,请求触发loadend事件后获取到的请求响应成功与否状态始终为false,由于Angualr2后来的版本也使用事件监听来处理拦截,有些地方就冲突了。
方式二:
出现问题总要解决吧,而后就采用方法一的升级版本,彻底重写XMLHttpRequest。
(function () { // create XMLHttpRequest proxy object var oldXMLHttpRequest = XMLHttpRequest; // define constructor for my proxy object window.XMLHttpRequest = function () { var actual = new oldXMLHttpRequest(); var self = this; this.onreadystatechange = null; // this is the actual handler on the real XMLHttpRequest object actual.onreadystatechange = function () { if (this.readyState == 1) { onLoadStart.call(this); } else if (this.readyState == 4) { if(this.status==200) onLoadEnd.call(this); else{ onError.call(this); } } if (self.onreadystatechange) { return self.onreadystatechange(); } }; // add all proxy getters ["status", "statusText", "responseType", "response", "readyState", "responseXML", "upload" ].forEach(function (item) { Object.defineProperty(self, item, { get: function () { return actual[item]; }, set: function (val) { actual[item] = val; } }); }); // add all proxy getters/setters ["ontimeout, timeout", "withCredentials", "onload", "onerror", "onprogress"].forEach(function (item) { Object.defineProperty(self, item, { get: function () { return actual[item]; }, set: function (val) { actual[item] = val; } }); }); // add all pure proxy pass-through methods ["addEventListener", "send", "open", "abort", "getAllResponseHeaders", "getResponseHeader", "overrideMimeType", "setRequestHeader", "removeEventListener" ].forEach(function (item) { Object.defineProperty(self, item, { value: function () { return actual[item].apply(actual, arguments); } }); }); } })();
如今咱们能够放心的拦截浏览器发出的请求了,妈妈不再用担忧个人学习了,哈哈。说一千道一万,来点干货,直接看项目。
传送门:web-monitor
喜欢请点个赞呗
或者去https://github.com/kisslove/w... Star一下
或者打赏一下
再或者……
哈哈,想法有点多了。