功能设计与抽象粒度
合理的设计是 底层部分:保留对全局封装的影响范围 项目层:保留对页面层的影响能力 页面层:保留对组件层的影响能力
需要考虑的功能点:
- 自定义 headers 添加
- 统一断网/弱网处理
- 接口缓存处理
- 接口统一错误提示
- 接口统一数据处理
- 统一数据层结合
-
axios 设计思想
功能特点:
在浏览器端,使用 XMLHttpRequest 发送请求
- 支持 Node.js 端发送请求
- 支持 Promise API,使用 Promise 风格语法
- 支持请求和响应拦截
- 支持自定义修改请求和返回内容
- 支持请求取消
- 默认支持 XSRF 防御
拦截器思想

赋予了分层开发时借助拦截行为,注入自定义能力的功能
axios 拦截器由以下步骤组成:
// lib/core/Axios.jsfunction Axios(instanceConfig) {this.defaults = instanceConfig;this.interceptors = {request: new InterceptorManager(),response: new InterceptorManager()};}// lib/core/InterceptorManager.jsfunction InterceptorManager() {// 存储所有的拦截器,但请求拦截器和响应拦截器是分开的this.handlers = [];}/*** 添加拦截器* fulfilled: 成功时执行的,在Promise.resolve中* rejected: 失败时执行的,在Promise.reject中** 返回当前添加的拦截器的ID,用于清除这个拦截器*/InterceptorManager.prototype.use = function use(fulfilled, rejected) {// 把传入的在resolve和reject中要执行的方法添加到数组中this.handlers.push({fulfilled: fulfilled,rejected: rejected,});return this.handlers.length - 1;};/*** 根据id请求拦截器** id: 刚才use方法返回的那个数据*/InterceptorManager.prototype.eject = function eject(id) {if (this.handlers[id]) {this.handlers[id] = null;}};/*** 迭代所有的拦截器** 这里会跳过之前使用eject方法设置为null的拦截器** @param {Function} fn 对所有拦截器都执行的一个方法*/InterceptorManager.prototype.forEach = function forEach(fn) {utils.forEach(this.handlers, function forEachHandler(h) {if (h !== null) {fn(h);}});};
任务编排
创建一个 chain 数组,把所有拦截器放进去,然后将请求拦截器插入到实际发送请求的方法前,响应拦截器插入该请求后

// dispatchRequest 用于请求数据,这里我们先展示不管怎么实现的// 这里把 dispatchRequest 也当做拦截器添加到队列中// 每2个是一组,前面用于Promise.resolve, 后面的1个用户Promise.rejectvar chain = [dispatchRequest, undefined];// 拦截器调用forEach方法,把每一个请求拦截器都添加到chain的前面this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {// 每2个是一组,前面用于Promise.resolve, 后面的1个用户Promise.reject// 由此也能看到,越是后添加的请求拦截器,越会是先执行chain.unshift(interceptor.fulfilled, interceptor.rejected);});// 拦截器调用forEach方法,把每一个响应拦截器都添加到chain的后面this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {// 响应拦截器按照顺序执行chain.push(interceptor.fulfilled, interceptor.rejected);});
任务调度
通过一个 While 循环,通过一个 Promise 实例,遍历迭代 chain 数组方法,并基于 Promise 回调特性,将各个拦截器串联执行起来。
// 把config初始化为一个Promise对象,方便后面的使用var promise = Promise.resolve(config);while (chain.length) {// 依次取出执行resolve和reject方法// 将执行后的结果传给下一个拦截器promise = promise.then(chain.shift(), chain.shift());}
适配器思想(Adapter)
安全思想
依赖双重 cookie 的方式防御 CSRF

