Secondary encapsulation (update) of axios based on common business scenarios

Posted by phillips321 on Thu, 17 Oct 2019 00:56:47 +0200

Update the second encapsulation of axios according to the common business scenarios under vue project after one year

Function realization:
1. Compatible with ie browser to avoid caching
2. Reduce or update duplicate requests
3. Interface domain name usage environment variable
4. Global loading status
5. Global error alerts that can be turned off
6. Global paging parameters can be enabled.
7...

Interceptor

/**
 * request interceptor 
 * @param  {} requestStart Request start
 */
service.interceptors.request.use(
  config => {
    requestStart({ config });
    return config;
  },
  error => {
    Message.error("Request error");
    Promise.reject(error);
  }
);
/**
 * Response interceptor
 * @param  {} requestEnd 1.End of request
 * @param  {} responseResolve 2.Request error handling
 */
service.interceptors.response.use(
  response => {
    const { status, data, config } = response;
    requestEnd({ config, data });
    return responseResolve({ status, data, config });
  },
  error => {
    if (axios.isCancel(error)) {
      Message.warning("In the network request, please do not repeat the operation!");
    } else {
      const { response } = error;
      Message.error({
        dangerouslyUseHTMLString: true,
        message: `<p>Request interface: ${
          response.config.url
        }</p><p>Request method : ${
          response.config.method
        }</p><p>Response state : ${response.status}</p><p>Response information : ${
          response.statusText
        }</p>`
      });
    }
    store.commit("setLoading", false);
    store.commit("setPageTotal", 0);
    return Promise.reject(error);
  }
);

Request start

  1. Processing request header
  2. Processing request parameters
  3. Processing duplicate requests
/**
 * Request start & & loading = true
 * @param  {} requestHeaders Request header
 * @param  {} requestParams Request parameters
 * @param  {} removePending Repeated requests
 */
const requestStart = ({ config } = {}) => {
  requestHeaders({ config });
  requestParams({ config });
  removePending({ config });
  addPending({ config });
  store.commit("setLoading", true);
};

Request response

  • Global error alert, which can be turned off in scenarios where a front-end custom alert is required
/**
 * @param  {} {status HTTP Status code
 * @param  {} data Response body
 * @param  {} config}={} AxiosRequestConfig
 */
const responseResolve = ({ status, data, config } = {}) => {
  const { code, text } = data;
  if (status === 200) {
    switch (code) {
      case 200:
        return Promise.resolve(data);
      case 900401:
        Message.error(text || "Login timeout, please login again!");
        window.location.href = process.env.VUE_APP_AUTH_URL;
        return Promise.reject(data);
      default:
        //Configurable error alert
        if (!config.headers["hide-message"]) {
          Message.error(text || "Operation failed!");
        }
        return Promise.reject(data);
    }
  } else {
    Message.error(text || "Operation failed!");
    store.commit("setLoading", false);
    return Promise.reject(data);
  }
};

End of request

  1. Processing duplicate requests
  2. Processing paging
  3. Processing loading status
/**
 * Request end & & loading = false
 * @param  {} {config}={} AxiosRequestConfig
 * @param  {} {config}={} response body
 */
const requestEnd = ({ config, data } = {}) => {
  removePending({ config });
  store.commit("setLoading", false);
  //Configuration paging
  if (config.headers.pagination) {
    const { data: content } = data;
    if (content) {
      store.commit("setPageTotal", content.total);
    }
  }
};

The following is the specific function realization

Request header preprocessing

  • Timestamp: avoid ie kernel browser caching
  • token
/**
 * Request header preprocessing
 * @param  {} {config} AxiosRequestConfig
 */
const requestHeaders = ({ config }) => {
  //1. timestamp
  const timestamp = new Date().getTime();
  config.headers.timestamp = timestamp;
  //2.token
  const token = sessionStorage.getItem("token");
  if (token) {
    config.headers.token = token;
  }
};

Request parameter preprocessing

  • Configurable global paging parameters are provided for list requests that need to use global paging components.
/**
 * Request parameter preprocessing
 * @param  {} {config}={} AxiosRequestConfig
 */
const requestParams = ({ config } = {}) => {
  //Configuration paging
  if (config.headers.pagination) {
    const { pageNum, pageSize } = store.getters.getPagination;
    config.data = Object.assign({}, config.data, {
      pageNum,
      pageSize
    });
  }
};

Processing duplicate requests

  • You can cancel the last request here as needed
/**
 * Processing duplicate requests
 * @param  {} {config}={} AxiosRequestConfig
 */
const addPending = ({ config }) => {
  const url =
    config.url + "&" + config.method + "&" + qs.stringify(config.data);
  config.cancelToken = new cancelToken(cancel => {
    if (!pending.some(item => item.url === url)) {
      pending.push({
        url,
        cancel
      });
    }
  });
};
const removePending = ({ config }) => {
  const url =
    config.url + "&" + config.method + "&" + qs.stringify(config.data);
  pending.forEach((item, index) => {
    if (item.url === url) {
      item.cancel("Cancel duplicate request:" + config.url);
      pending.splice(index, 1);
    }
  });
};

Complete code

import { Message } from "element-ui";
import axios from "axios";
import store from "../store/index";
const qs = require("qs");

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 100000
});

const pending = [];
const cancelToken = axios.CancelToken;

/**
 * Processing duplicate requests
 * @param  {} {config}={} AxiosRequestConfig
 */
const addPending = ({ config }) => {
  const url =
    config.url + "&" + config.method + "&" + qs.stringify(config.data);
  config.cancelToken = new cancelToken(cancel => {
    if (!pending.some(item => item.url === url)) {
      pending.push({
        url,
        cancel
      });
    }
  });
};
const removePending = ({ config }) => {
  const url =
    config.url + "&" + config.method + "&" + qs.stringify(config.data);
  pending.forEach((item, index) => {
    if (item.url === url) {
      item.cancel("Cancel duplicate request:" + config.url);
      pending.splice(index, 1);
    }
  });
};
/**
 * Request header preprocessing
 * @param  {} {config} AxiosRequestConfig
 */
const requestHeaders = ({ config }) => {
  //1. timestamp
  const timestamp = new Date().getTime();
  config.headers.timestamp = timestamp;
  //2.token
  const token = sessionStorage.getItem("token");
  if (token) {
    config.headers.token = token;
  }
};
/**
 * Request parameter preprocessing
 * @param  {} {config}={} AxiosRequestConfig
 */
const requestParams = ({ config } = {}) => {
  //Configuration paging
  if (config.headers.pagination) {
    const { pageNum, pageSize } = store.getters.getPagination;
    config.data = Object.assign({}, config.data, {
      pageNum,
      pageSize
    });
  }
};
/**
 * Request start & & loading = true
 * @param  {} requestHeaders 1.Configuration request header
 * @param  {} requestParams 2.Configuration request body
 * @param  {} removePending 3.Processing duplicate requests
 */
const requestStart = ({ config } = {}) => {
  requestHeaders({ config });
  requestParams({ config });
  removePending({ config });
  addPending({ config });
  store.commit("setLoading", true);
};
/**
 * Request end & & loading = false
 * @param  {} {config}={} AxiosRequestConfig
 * @param  {} {config}={} response body
 */
const requestEnd = ({ config, data } = {}) => {
  removePending({ config });
  store.commit("setLoading", false);
  //Configuration paging
  if (config.headers.pagination) {
    const { data: content } = data;
    if (content) {
      store.commit("setPageTotal", content.total);
    }
  }
};
/**
 * @param  {} {status HTTP Status code
 * @param  {} data Response body
 * @param  {} config}={} AxiosRequestConfig
 */
const responseResolve = ({ status, data, config } = {}) => {
  const { code, text } = data;
  if (status === 200) {
    switch (code) {
      case 200:
        return Promise.resolve(data);
      case 900401:
        Message.error(text || "Login timeout, please login again!");
        window.location.href = process.env.VUE_APP_AUTH_URL;
        return Promise.reject(data);
      default:
        //Configurable error alert
        if (!config.headers["hide-message"]) {
          Message.error(text || "Operation failed!");
        }
        return Promise.reject(data);
    }
  } else {
    Message.error(text || "Operation failed!");
    store.commit("setLoading", false);
    return Promise.reject(data);
  }
};
/**
 * request interceptor 
 * @param  {} requestStart Request start
 */
service.interceptors.request.use(
  config => {
    requestStart({ config });
    return config;
  },
  error => {
    Message.error("Request error");
    Promise.reject(error);
  }
);
/**
 * Response interceptor
 * @param  {} requestEnd 1.End of request
 * @param  {} responseResolve 2.Request error handling
 */
service.interceptors.response.use(
  response => {
    const { status, data, config } = response;
    requestEnd({ config, data });
    return responseResolve({ status, data, config });
  },
  error => {
    if (axios.isCancel(error)) {
      Message.warning("In the network request, please do not repeat the operation!");
    } else {
      const { response } = error;
      Message.error({
        dangerouslyUseHTMLString: true,
        message: `<p>Request interface: ${
          response.config.url
        }</p><p>Request method : ${
          response.config.method
        }</p><p>Response state : ${response.status}</p><p>Response information : ${
          response.statusText
        }</p>`
      });
    }
    store.commit("setLoading", false);
    store.commit("setPageTotal", 0);
    return Promise.reject(error);
  }
);

export default service;

Topics: Javascript axios IE network Vue