oakland / tecblog

My tech blogs
4 stars 0 forks source link

axios 封装 #282

Open oakland opened 3 years ago

oakland commented 3 years ago

是一次很好的学习和尝试的机会 会对各种错误有了解,断网、后端 status 不为 200,后端 200 但是 response_code 不为 0,如果可以的话最好对后端返回数据有 schema 的校验,这种就完美了。 然后对于设计模式有很好的了解,可以深入理解一下。

这次封装想支持的功能很多:

总之这次想实现的封装效果太多,然后就一直下不了手。也看了很多文章,发现各个项目的情况也不尽相同,所以还是没有下手。

但是我后来想了一下,感觉我想要做的太多了,而且想的多,做的少,所以导致迟迟不能推进。

后来我想了下,觉得:

  1. 可以尝试先实现一部分功能,再逐步修改和完善,不要想着可以一次性就写的完美。axios 也不是一次就写成的,也是逐步升级的。
  2. 一些特殊的,项目中使用很少的效果和功能,不一定非得添加到封装之中,可以单独使用 axios 去做就行了,不一定封装非得满足所有功能,特殊的少量功能单独封装就行,否则也可能会导致过度封装,返回封装的代码也因为很多不必要的功能可读性也会变差 在以上两个原则的指导下,我觉得可以动手写起来了。逐步完善。

写着写着,发现可以把错误进行分类,让不同的错误由不同的 layer 来处理。比如请求层的错误,404, 500 等,统一由请求层来处理,就是 axios 来捕获进行处理。但是业务层的错误,例如 response_code === - 1这种属于业务层的错误,统一由业务层来进行处理,也就是说业务层只可能拿到 response_code === - 1 的情况,不用担心会有 404 这种错误。这样处理起来更有逻辑?

为了避免 axios 对全局 axios 的修改,所以通过 axios.create() 的方式对封装的 axios 创建了一个实例,这样每次引入的都是一个新的 axios。

怎么识别前端 timeout 的错误呢?难道只有硬编码?但是担心 axios 改了自己的 timeout 错误提示。

// adapter allows custom handling of requests which makes testing easier. // Return a promise and supply a valid response (see lib/adapters/README.md). adapter: function (config) { / ... / },

感觉可以用 adapter 来做测试。

还可以考虑在请求的层面做错误上报和监控,把错误的内容发给服务器。

oakland commented 3 years ago

在尝试封装的过程中,看到了很多不同封装理念,摘录一些,并做点评。 https://gist.github.com/paulsturgess/ebfae1d1ac1779f18487d3dee80d1258

import axios from 'axios';

class Service {
  constructor() {
    let service = axios.create({
      headers: {csrf: 'token'}
    });
    service.interceptors.response.use(this.handleSuccess, this.handleError);
    this.service = service;
  }

  handleSuccess(response) {
    return response;
  }

  handleError = (error) => {
    switch (error.response.status) {
      case 401:
        this.redirectTo(document, '/')
        break;
      case 404:
        this.redirectTo(document, '/404')
        break;
      default:
        this.redirectTo(document, '/500')
        break;
    }
    return Promise.reject(error)
  }

  redirectTo = (document, path) => {
    document.location = path
  }

  get(path, callback) {
    return this.service.get(path).then(
      (response) => callback(response.status, response.data)
    );
  }

  patch(path, payload, callback) {
    return this.service.request({
      method: 'PATCH',
      url: path,
      responseType: 'json',
      data: payload
    }).then((response) => callback(response.status, response.data));
  }

  post(path, payload, callback) {
    return this.service.request({
      method: 'POST',
      url: path,
      responseType: 'json',
      data: payload
    }).then((response) => callback(response.status, response.data));
  }
}

export default new Service;

在这个封装的过程中看到了几个不错的理念:

  1. 用 class 进行封装
  2. 除了通用配置之外,把 get, patch 和 post 也单独封装出来了。
  3. 封装的时候添加了 axios 没有的 callback,实际上通常的业务逻辑都需要有这个 callback 的逻辑。但是 axios 并没有提供,需要你自己封装来提供。
oakland commented 3 years ago

最近看到有人分享这个 react 的 hooks,use-http ,感觉里面有我想要实现的各种功能,是不是可以在项目中使用呢?可以考虑考虑。