实现DoKit Web端请求捕获工具(四)读chobitsu源码

·  阅读 1215
实现DoKit Web端请求捕获工具(四)读chobitsu源码

一、前言

上一节的结论中,我们在研究了Eruda中Network.js后,发现了chobitsu这个chrome devtools协议工具,Eruda实现请求拦截是通过调用它实现的,通过传入了四个对象,获得了request的响应信息。但要想具体了解请求捕获的实现方案,还需要带着以下问题继续阅读chobitsu的源码:

  • 怎么获得request list的,是在真正发送请求之前吗?
  • 何时发送的请求,在请求发送前都做了什么?
  • 获得response信息是chobitsu自行发送了请求后记录了response信息,还是直接记录了浏览器发送请求所获得的response?
  • chobitsu是怎么拦截请求的,是它重写了浏览器发送请求的send方法,在原有的send前做了些其他事吗?

二、关于请求拦截器的准备知识

首先,浏览器中数据请求有两种方式,XMLHttpRequest和fetch,其中AJAX全称“Asynchronous JavaScript and XML”,是一种创建交互式网页应用的网页开发技术,其本质就是使用XMLHttpRequest来请求数据。在我们的请求拦截器中两种捕获方式都要实现。两种获取方式如下所示:

  • XMLHttpRequest请求数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
  console.log(xhr.response);
};

xhr.onerror = function() {
  console.log("Oops, error");
};

xhr.send();
  • fetch请求数据
fetch(url)
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(e => console.log("Oops, error", e))

fetch请求属于promise结构,直接.then()方法处理回调数据,当出错时,会执行catch方法,而且promise避免了回调金字塔的问题。

三、chobitsu源码目录解析

  1. src目录下文件结构如下:
  1. 项目的主要代码在src中,src目录如下,包含domains和lib两个目录和index.ts。
  • index.ts是整个项目的入口文件,其中包括chobitsu的类定义;
  • domains中包括Storage、Runtime、Network、DOM、DOMDebugger、DOMStorage、Overlay、Page、Debugger、CSS这些功能模块的ts文件,还包括methods.ts,其中将上面每个功能模块中实现的方法,以“功能模块名.方法名:方法变量”的形式,逐一放入methods常量中。在index.ts中会引用methods常量,从中取到function变量。
  • lib中是2.中的功能模块会公共调用到的工具类,其中与请求相关的有connector.ts、request.ts等。
  • 另外可以看到,大部分功能模块及公共模块的实现都调用了和chobitsu、eruda同一个作者的另一个项目:licia,它提供了丰富的JavaScript工具库,如大小写格式转换、URL转换、计数等,可查看官方地址

四、lib目录下的公共模块

lib中connector.ts、mutationObserver.ts、request.ts三个文件中分别定义了四个类Connector、Observer、XhrRequest和FetchRequest,这三个类都继承于licia中的Emitter类。

image.png

通过查看licia的使用文档,我们可以知道Emitter用于提供观察者模式的 Event emitter类,以下引自licia使用文档

Emitter

提供观察者模式的 Event emitter 类。

类型定义
class Emitter {
    on(event: string, listener: types.AnyFn): Emitter;
    off(event: string, listener: types.AnyFn): Emitter;
    once(event: string, listener: types.AnyFn): Emitter;
    emit(event: string, ...args: any[]): Emitter;
    removeAllListeners(event?: string): Emitter;
    static mixin(obj: any): any;
}

on: 绑定事件。

off: 解绑事件。

once: 绑定只触发一次的事件。

参数名说明
event事件名称
listener事件监听器

emit: 触发事件。

参数名说明
event事件名称
...args传递给监听器的参数

removeAllListeners: 解绑所有事件。

参数名说明
event事件名称

mixin:【静态】 将 Emitter 类的方法绑定到指定对象上去。

参数名说明
obj目标对象
const event = new Emitter();
event.on('test', function(name) {
    console.log(name);
});
event.emit('test', 'licia'); // Logs out 'licia'.
Emitter.mixin({});

总结来说四个子类分别用Emitter提供的on/off/once/emit/removeAllListeners/mixin的方法管理事件绑定。

在上一篇文章中,我们知道了eruda的Network插件就是通过const network = chobitsu.domain('Network')得到chobitsu中名为Network的domainMethod,在通过network.on('requestWillBeSent', this._reqWillBeSent)来绑定

  • mutationObserver用于监视对DOM树所做的更改;

三个文件都在都定义了相应的类XhrRequest、FetchRequest和Connector,这三个类都继承于licia中的Emitter类。

六、本节总结

本节的主要结论是研究了Network.js源码后,发现了chobitsu这个chrome devtools协议工具,Eruda实现请求拦截是通过调用它实现的,本节研究了Eruda项目中是怎么调用它的,主要是传入了四个对象,获得了request的响应信息。

但要想具体了解请求捕获的实现方案,还需要带着以下问题继续阅读chobitsu的源码:

  • 怎么获得request list的,是在真正发送请求之前吗?
  • 何时发送的请求,在请求发送前都做了什么?
  • 获得response信息是chobitsu自行发送了请求后记录了response信息,还是直接记录了浏览器发送请求所获得的response?
  • chobitsu是怎么拦截请求的,是它重写了浏览器发送请求的send方法,在原有的send前做了些其他事吗?

七、文章索引

实现DoKit Web端请求捕获工具(一)产品调研

实现DoKit Web端请求捕获工具(二)读Eruda源码上

实现DoKit Web端请求捕获工具(三)读Eruda源码下

分类:
开发工具
标签:
分类:
开发工具
标签:
收藏成功!
已添加到「」, 点击更改