在前端监控系统中, 或者其他场景下, 如果我们需要监控当前页面下所有请求状态. 可能通常请求下, 我们会选择在请求的回调中去处理. 这种做法的缺点就是会侵入具体的业务代码. 在通常的监控中, 监控部分的代码和业务部分的代码是分离的. 此外, 如果存在很多的请求需要被监听, 通过侵入具体业务代码, 为了减少代码的重复, 也需要封装监听请求的逻辑.
本文通过 monkey patches 的方法实现了一个 request-interceptor 包, 可以按需求监听请求.
该 NPM 包的项目地址为: 欢迎使用.
获取 API 请求的状态和结果
monkey patches 实现监控 XMLHttpRequest 请求
monkey patches 实现监控 fetch 请求
本文的原文在我的博客中: https://github.com/forthealllight/blog/issues/40
欢迎 star
一, 获取 API 请求和结果
获取请求的方式包含了 fetch 和 XMLHttpRequest. 比如下面是一个 XMLHttpRequest 请求的例子:
- var client = new XMLHttpRequest();
- client.open("POST","http://10.12.72.16:8080/extraInfo" );
- client.setRequestHeader("Content-Type", "application/json; charset=utf-8");
- client.send(JSON.stringify({
- }));
通常我们会通过 client 上出发的 readystatechange 来判断请求的状态以及得到请求的响应结果:
- client.onreadystatechange = function () {
- if (client .readyState==4 &&client.status==200) {
- console.log(client.responseText);//
- }
- }
XMLHttpRequest 的 prototype 除了 onreadystatechange 事件外还有其他很多事件, 比如 onabout,onerror,onload,onloadstart 等等事件. 如果我们要完整的监听一个请求, 那么需要实现完整的实现这些事件:
- client.onabout = function(){}
- client.onerror = function(){}
- clinet.onload = function(){}
- client.onloadstart = function(){}
- ....
此外如果当某一个事件发生时, 需要按顺序的实行一系列的函数, 这样会使得事件函数内部越来越复杂, 使得整体项目变的无法维护.
fetch 请求也是同理, 因此我们需要合理的封装监听请求的逻辑.
二, monkey patches 实现监控 XMLHttpRequest 请求
本文不会具体介绍如何通过 monkey patches 来封装监听请求的逻辑, 该逻辑已经在我的 NPM 包中实现, 具体可以参考我的开源项目:
本文只介绍如何使用, 如有兴趣, 可以读一读具体如何实现这个 monkey patches, 在目录的 source 文件夹中, 如有疑问, 可以提 issue.
该 NPM 包的包名为: req-interceptor. 首先来看对于 XMLHttpRequest 请求如何使用:
- import { ajaxIntercept } from 'req-interceptor';
- // 监听
- const unregister = ajaxIntercept.register({
- requestAbout: function (xhr) {
- // xhr is real instance of a request
- console.log(xhr)
- },
- requestError: function (xhr) {
- // xhr is real instance of a request
- console.log(xhr)
- },
- requestLoad: function (xhr) {
- // xhr is real instance of a request
- console.log(xhr)
- },
- });
- // 发送请求
- var client = new XMLHttpRequest();
- client.open("POST","http://10.12.72.16:8080/extraInfo" );
- client.setRequestHeader("Content-Type", "application/json; charset=utf-8");
- client.send(JSON.stringify({}));
只需要在发送请求前先调用 ajaxIntercept.register 函数传入监听的对象, 该函数会返回一个取消监听的方法.
这样就监听之后的任意请求, 在 ajaxIntercept.register 中的实际参数的对象中, 对象的属性是一个函数, 参数为 xhr,xhr 就是一个被监听的 XMLHttpRquest, 因此我们可以从 xhr 中拿到请求的具体响应. xhr 的一个例子为:
- xhr = {
- readyState: 4
- response: "{"success":0}"
- responseText: "{"success":0}"
- responseType: "" responseURL:"http://10.12.72.16:8080/extraInfo"
- responseXML: null
- status: 201
- statusText: "Created"
- timeout: 0
- }
如果我们在取消对于某一个请求的监听, 则调用该返回的 unregister 函数, 此后请求不会再被监听.
unregister();
此外我们也可以在某一个请求前添加多个监听函数:
- import {
- ajaxIntercept
- } from 'req-interceptor';
- // 监听
- const unregister1 = ajaxIntercept.register({
- ...
- });
- const unregister2 = ajaxIntercept.register({
- ...
- });
- const unregister3 = ajaxIntercept.register({
- ...
- });
- // 请求
- client.open(url,....)
如果我们想要一次性移除所有的对于请求的监听函数, 可以直接调用:
ajaxIntercept.clear();
三, monkey patches 实现监控 fetch 请求
对于 fetch 请求也是一样的.
- import { fetchIntercept } from 'req-interceptor';
- import { fetchIntercept } from 'req-interceptor';
- const unregister = fetchIntercept.register({
- request: function (url, config) {
- // Modify the url or config here
- return [url, config];
- },
- requestError: function (error) {
- // Called when an error occured during another 'request' interceptor call
- return Promise.reject(error);
- },
- response: function (response) {
- // Modify the reponse object
- return response;
- },
- responseError: function (error) {
- // Handle an fetch error
- return Promise.reject(error);
- }
- });
- // Call fetch to see your interceptors in action.
- fetch('http://google.com');
不同的是, fetch 不像 XMLHttpRequest 请求那样, 可以监听完整的过程, fetch 只有 request,requestError,response 和 responseError 这 4 个属性可以监听, 分别映射请求的参数, 请求失败, 请求返回成功, 请求返回失败.
同样的也可以通过返回函数来取消监听, 以及通过 clear 函数来取消所有监听函数.
来源: https://juejin.im/post/5c441eb36fb9a049eb3c3cb9