④ 版本② axios 封装

HttpRequestBase 类

1 构造函数

constructor(baseUrl) {
  const basePort = getUrlPort(baseUrl);

  this.baseUrl = baseUrl;
  this.baseUrlWithPort2 = baseUrl.replace(/(\/\/.*:)(\d+)/, `$1${basePort + 1}`);
  this.basePort = basePort; // 原始端口
  this.queue = {};
  this.triggerTime = '';
  this.alikeUrl = []; // ajax标识--请求地址&请求方式
  this.CancelToken = axios.CancelToken;

  // 在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
  this.removeAlikeUrl = config => {
    // 截取 baseUrl 后的字符串
    let configUrl =
      config.url.indexOf(config.baseURL) !== -1
        ? config.url.substring(config.baseURL.length, config.url.length)
        : config.url;
    for (var i = this.alikeUrl.length - 1; i >= 0; i--) {
      if (this.alikeUrl[i].u === configUrl + '&' + config.method) {
        this.alikeUrl[i].cancel('axios请求被取消');
        this.alikeUrl.splice(i, 1);
        break;
      }
    }
  };
}

2 事件处理程序

2.1 请求封装

request(options) {
  // 创建 axios 请求
  const instance = axios.create();
  // 请求参数处理
  options = this.getInsideConfig(options);
  // 请求响应拦截
  this.interceptors(instance, options.url);
  return instance(options);
}

2.2 请求参数处理

  • transformRequest 允许在向服务器发送前修改请求数据,只能用put post patch请求方法
getFinalBaseURL(apiUrl) {
  return checkIsUsePort2(apiUrl, this.basePort) ? this.baseUrlWithPort2 : this.baseUrl;
}
getInsideConfig(options) {
  const config = {
    baseURL: this.getFinalBaseURL(options.url),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      Authorization: SessionIdConfigure.getLocalId()
    },
    // 在向服务器发送前修改请求数据
    transformRequest: [
      data => {
        let ret = '';

        for (var i in data) {
          if (data[i] instanceof Array) {
            for (var j in data[i]) {
              ret += i + '=' + (
                typeof data[i][j] === 'object'
                  ? JSON.stringify(data[i][j])
                  : encodeURIComponent(data[i][j])
                ) + '&';
            }
          } else {
            if (
              !(String(data[i]) === 'null' || String(data[i]) === 'undefined') &&
              String(data[i]).indexOf('NaN-aN-aN') === -1
            ) {
              ret += i + '=' + encodeURIComponent(data[i]) + '&';
            } else {
              ret += i + '=&';
            }
          }
        }

        return ret;
      }
    ],
    ...options
  }

  return config;
}

2.3 取消loading效果

destroy(url) {
  if (this.queue[url]) delete this.queue[url];

  if (!Object.keys(this.queue).length) {
    store.commit('appLoading/display', false);
  }
}

2.4 请求响应拦截处理

interceptors(instance, url) {
  let isNoSpin = proStorage.fetch('noSpin');
  isNoSpin && proStorage.save('noSpin', 'false');

  // 请求拦截
  // 响应拦截
}
  • 请求拦截
/**
 * 请求拦截
 * @property {Function} config.cancelTrigger 可传入自定义请求取消方法
 */
instance.interceptors.request.use(
  config => {
    this.removeAlikeUrl(config); //在一个ajax发送前执行一下取消操作

    let cancelTrigger = config.cancelTrigger;
    if (!config.cancelTrigger) {
      config.cancelToken = new this.CancelToken(c => {
        cancelTrigger = c;
      });
    }
    // ajax标识--请求地址&请求方式
    this.alikeUrl.push({ u: config.url + '&' + config.method, cancel: cancelTrigger });

    // 触发时间
    this.triggerTime = new Date();
    // 添加全局的loading...
    if (!Object.keys(this.queue).length && (!isNoSpin || isNoSpin === 'false')) {
      store.commit('appLoading/display', true);
    }

    if (!isNoSpin || isNoSpin === 'false') {
      this.queue[url] = true;
    }

    isNoSpin = null;
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);
  • 响应拦截
instance.interceptors.response.use(
  res => {
    // 在一个ajax响应后再执行一下取消操作
    this.removeAlikeUrl(res.config);
    this.destroy(url);
    const { data, status } = res;

    const {
      config: { method }
    } = JSON.parse(JSON.stringify(res));
    if (
      store.state.interfaceLog.storageLog.developmentOff &&
      url.indexOf('analysis/api/') !== -1 &&
      method === 'post' &&
      data.code === 1
    ) {
      let query_key, query_name, query_time, exec_time;
      if (data.data && Object.keys(data.data).length > 0) {
        query_key = data.data['query_key'];
        query_name = data.data['query_name'];
        query_time = data.data['query_time'];
        exec_time = data.data['exec_time'];
      } else if (data.os_data && data.os_data[0] && Object.keys(data.os_data[0]).length > 0) {
        query_key = data.os_data[0].data['query_key'];
        query_name = data.os_data[0].data['query_name'];
        query_time = data.os_data[0].data['query_time'];
        exec_time = data.os_data[0].data['exec_time'];
      }
      const logData = {
        url,
        query_key,
        query_name,
        query_time,
        exec_time,
        title: router.currentRoute.meta.title,
        param: res.config.data,
        triggerTime: this.triggerTime,
        msg: data.msg
      };
      store.commit('addStorageLog', logData);
    }

    interceptResponse(data.code);

    return { data, status };
  },
  error => {
    this.destroy(url);
    console.error('response: ', typeof error === 'object' ? error.message : error);

    if (!axios.isCancel(error)) {
      this.removeAlikeUrl(error.config);
      let errorInfo = error.response;

      if (!errorInfo) {
        const {
          request: { statusText, status },
          config
        } = error;
        errorInfo = {
          statusText,
          status,
          request: { responseURL: config.url }
        };
      }
      interceptResponse(errorInfo.status);
    }

    return Promise.reject(error);
  }
);

2.5 类外方法

  • 请求过期提示
function interceptResponse(status) {
  if (status === 401 && router.currentRoute.name !== 'Login') {
    Modal.warning({
      title: '提示',
      content: 'Session已过期!请您确认返回登录页面重新登录!',
      onOk: () => {
        store.commit('user/logout');
      }
    })
  }
}
  • 是否使用第二端口
// 以 /analysis 和 /query 开头的接口需切换端口,现在的匹配模式包含了前后的'/'符号
function checkIsUsePort2(url, basePort) {
  return (basePort === 9001 || basePort >= 30000) && /^\/(analysis|query)[^/]*\//.test(url);
}
  • 获取地址端口号
function getUrlPort(url) {
  let result = url.match(/\/\/.*:(\d+)/);
  return result && Number(result[1]);
}
posted on 2023-02-09 11:48  pleaseAnswer  阅读(23)  评论(0编辑  收藏  举报