美文网首页
基于axios和react的httpclient封装

基于axios和react的httpclient封装

作者: Mr无愧于心 | 来源:发表于2022-04-11 20:31 被阅读0次
    import axios from 'axios';
    import { message } from 'antd';
    import React from 'react';
    import stores from '../stores';
    /**
     * 支持常用的请求方法包括 ['get', 'delete', 'head', 'post', 'put', 'options']
     * 对外暴露的实例如下
     * 1:HttpClient 满足全局loading样式(需要配合mobx的store管理全局状态)
     * 2:HttpClientOnly 满足不展示对应loading
     * 3:HttpClientPart 满足局部loading(需要配合mobx的store管理全局状态)
    */
    axios.defaults.headers['Cache-Control'] = 'no-store,no-cache,no-transform,must-revalidate,max-age=0';
    class BaseHttpClient {
      constructor(partName) {
        this.partName = partName;
        this.methods = ['get', 'delete', 'head', 'post', 'put', 'options'];
        this.methods.forEach((item) => {
          this[item] = (url, params = {}, headers = {}) => this.commonMethod(item, url, params, headers)
        })
      }
    
      baseUrl = '';
    
      instance = axios.create({
        baseURL: this.baseUrl,
        timeout: 20000,
        withCredentials: true,
      });
    
      commonMethod (method, url, params = {}, headers) {
        this.url = url
        this.loading && !this.part && stores.gStore.increment();// 增加全局loading状态
        this.loading && this.part && stores.gStore.updateLoadingPart(this.partName, true)// 设置局部loading状态
        let allParams = [url, { params, ...headers = {} }]
        if (['get', 'delete', 'head', 'options'].includes(method)) { // get系请求
          allParams = [url, { params, ...headers }]
        } else if (['post', 'put'].includes(method)) { // post系请求
          allParams = [url, params, headers];
        }
        return this.instance[method](...allParams)
          .then(this.handleSuccessResponse.bind(this))
          .catch(this.handleErrorResponse.bind(this))
          .finally(() => {
            this.loading && !this.part && stores.gStore.reduce();// 减少全局loading()
            this.loading && this.part && stores.gStore.updateLoadingPart(this.partName, false)// 删除局部loading状态
          });
      }
    
      handleSuccessResponse (res) {// 请求成功}
    
      handleErrorResponse (err) { //报错处理}
    }
    
    function withLoading (loading, part) {
      return (target) => {
        // eslint-disable-next-line no-param-reassign
        target.prototype.loading = loading; // 是否需要loading
        target.prototype.part = part;// 是否需要局部loading
      };
    }
    
    // 带有拦截器的HttpClient
    class HttpClientWithInterceptors extends BaseHttpClient {
      constructor() {
        super()
        this.instance.interceptors.response.use(
          (response) => response, // 在这里添加响应的拦截
          (error) => {
            const originalRequest = error.config
            if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1 && !originalRequest._retry) {
              message.error('查询超时,请稍后重试')
            }
          },
        );
      }
    }
    
    @withLoading(true)
    class HttpClientClass extends HttpClientWithInterceptors { }
    @withLoading(true, true)
    class HttpClientPartClass extends HttpClientWithInterceptors {
      constructor(partName) {
        super();
        this.partName = partName;
      }
    }
    @withLoading(false)
    class HttpClientOnlyClass extends HttpClientWithInterceptors { }
    
    export const HttpClient = new HttpClientClass();
    export const HttpClientOnly = new HttpClientOnlyClass();
    export const HttpClientPart = (partName) => new HttpClientPartClass(partName);
    
    //---------------------mobx的store------------------------------
    // gStore
    @observable loadingPart = {}// 存放局部loading的组件标志
    
    @computed get loading() {// 展示全局loading
        return this.httpCount !== 0;
    }
    @action increment() {
        this.httpCount += 1;
    }
    
    @action reduce() {
        this.httpCount -= 1;
     }
    @action updateLoadingPart = (partName, loading) => {
        this.loadingPart[partName] = loading;
    }
    // -----------------------------------
    <Spin spinning={stores.gStore.loading}></Spin>// 全局加载
    <Spin spinning={stores.gStore.loadingPart.xxx}></Spin>// 局部加载
    

    相关文章

      网友评论

          本文标题:基于axios和react的httpclient封装

          本文链接:https://www.haomeiwen.com/subject/ogdwsrtx.html