资讯专栏INFORMATION COLUMN

前端监控数据收集(请求拦截)

娣辩孩 / 2900人阅读

摘要:的五种就绪状态请求未初始化还没有调用。请求已发送,正在处理中通常现在可以从响应中获取内容头。并且还提供了每个阶段的事件如果请求中止,会触发事件。网络错误如太多重定向会阻止请求完成,会触发事件。当等待服务器的响应时,对象会发生事件。

所谓web,即使你我素未谋面,便知志趣相投;足不出户,亦知世界之大。

01 — 为什么拦截请求

现在的web应用,大都是通过请求(http)去获取资源,拿到资源后再呈现给用户,一个页面中可以有多个这样的请求。每一次请求的开始,等待,完成,异常都会有相应的状态来标识。我们在自己的框架中通常都会使用一个全局过滤器,来拦截请求,目的大同小异:

在发送请求之前,修改请求参数,添加请求头

请求发送中的进度计算(通常是文件上传)

请求出错后的捕获

请求结束后,处理后台返回数据结构,进行适配

……

看看请求的整个流程图:

而我们最常用的发送请求的便是XMLHttpRequest。

XMLHttpRequest.readyState的五种就绪状态:

0:请求未初始化(还没有调用 open())。

1:请求已经建立,但是还没有发送(还没有调用 send())。

2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)。

3:请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成。

4:响应已完成;您可以获取并使用服务器的响应了。

并且XMLHttpRequest还提供了每个阶段的事件:

abort

如果请求中止,会触发abort事件。

error

网络错误(如太多重定向)会阻止请求完成,会触发error事件。

load

当事件完成,会触发load事件。

loadend

当一个请求完成,无论成功(load)或者不成功(abort/error)后触发

loadstart

当调用send()时,触发单个loadstart事件。

progress

当等待服务器的响应时,XHR对象会发生progress事件。通常每隔50毫秒左右,所以可以使用这事件给用户反馈请求的进度。

timeout

当等待服务器的响应超时会触发。

02 — 如何拦截请求

了解了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);
    }
   });
  });
  }
})();




03 — 项目实战

现在我们可以放心的拦截浏览器发出的请求了,妈妈再也不用担心我的学习了,哈哈。说一千道一万,来点干货,直接看项目。

传送门:web-monitor


喜欢请点个赞呗

或者去https://github.com/kisslove/w... Star一下

或者打赏一下

再或者……

哈哈,想法有点多了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/19484.html

相关文章

  • 前端监控数据收集请求拦截

    摘要:的五种就绪状态请求未初始化还没有调用。请求已发送,正在处理中通常现在可以从响应中获取内容头。并且还提供了每个阶段的事件如果请求中止,会触发事件。网络错误如太多重定向会阻止请求完成,会触发事件。当等待服务器的响应时,对象会发生事件。 所谓web,即使你我素未谋面,便知志趣相投;足不出户,亦知世界之大。 01 — 为什么拦截请求 现在的web应用,大都是通过请求(http)去获取资源,拿到...

    IntMain 评论0 收藏0
  • JS实现监控微信小程序

    摘要:博客地址使用模块化工具打包自己开发的库文章中有提到,当时需要写一个,监控小程序的后台接口调用和页面报错,今天就来说下实现原理吧原理之前也做过浏览器端的数据埋点上报,其实原理大同小异通过劫持原始方法,获取需要上报的数据,最后再执行原始方法,这 博客地址 《使用模块化工具打包自己开发的JS库》文章中有提到,当时需要写一个SDK,监控小程序的后台接口调用和页面报错,今天就来说下实现原理吧! ...

    Cheriselalala 评论0 收藏0
  • 如何实现一个IOS网络监控组件

    摘要:此文由作者朱志强授权网易云社区发布。代码演示核心代码将原方法放在中声明函数指针实现函数使用系统方法的函数指针完成系统的实现在这里获取到了系统方法调用的时机在程序启动后调用对委托模型的监控替换方法时需要指定类名,而的的类并不确定。 此文由作者朱志强授权网易云社区发布。 Mobile Application Monitor IOS组件设计技术分享 背景应用程序性能管理Application...

    xbynet 评论0 收藏0
  • HelloType:JS运行时数据类型检查工具

    摘要:进入主页使用文档是一个设计简单的运行时的数据类型检查工具,它可以帮助你的程序在使用某个组变量前,对变量的数据类型进行检查,防止在使用变量进行运算时由于数据类型不同导致报错。 showImg(https://segmentfault.com/img/bVbfW41?w=1380&h=500); 进入GitHub主页使用文档 HelloType是一个api设计简单的js运行时的数据类型检查...

    Heier 评论0 收藏0

发表评论

0条评论

娣辩孩

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<