自学内容网 自学内容网

Axios封装一款前端项目网络请求实用插件

前端项目开发非常经典的插件axios大家都很熟悉,它是一个Promise网络请求库,可以用于浏览器和 node.js 支持的项目中。像一直以来比较火的Vue.js开发的几乎所有项目网络请求用的都是axios。那么我们在实际的项目中,有时候为了便于维护、请求头信息统一处理、统一拦截器设置以及响应数据统一处理,需要在项目中针对axios封装一个网络请求插件。接下来就介绍一下针对以上这些输出具体的解决方案和步骤。

封装前准备(安装axios插件)
#安装前先确定node.js版本,可以前往下载对应的nodejs版本:https://nodejs.org/zh-cn/download
yarn add axios

在这里插入图片描述

创建一个网络请求组件(用于提供对外访问)

axios-utils.js

/**
 * 能用网络请求
 * @param method {'GET'|'PUT'|'POST'|'DELETE'} 请求方式
 * @param url 请求相对或完整路径
 * @param params 请求对象参数
 * @param headers 请求头对象参数
 * @param thenCall 当请求状态码返回非成功或非对象时回调,便于异常数据统一处理
 * @returns {*} Promise
 */
export function axiosapi(method = "post", url = '', params = {}, headers = {}, thenCall) {
  //创建axios对象实例
  let instance = axios.create({
    baseURL: "/api", //根url地址,这里设置的是代理地址(请看下面配置)
    //在跨域请求时,这个属性特别重要。根据浏览器的同源策略,为了安全起见,浏览器会阻止跨源HTTP请求。
    //通过设置 withCredentials为true,可以允许跨域请求时携带证书信息,从而绕过这个限制。
    withCredentials: true,
    //公共请求头信息设置
    headers: {
      "token": getToken(),
      "version": "1.0.2"
    }
  });
  //设置本次网络请求拦截器
  instance.interceptors.request.use((config) => {
    //这里处理你的请求拦截信息
    return config;
  }, function (error) {
    return Promise.reject(error);
  });
  //设置本次网络请求响应拦截器
  instance.interceptors.response.use((res) => {
    //这里处理你的响应拦截信息
    return res;
  }, (error) => {
    //解决请求异常时网页出现ERR_BAD_REQUEST错误导致功能不能使用情况,需要返回空的Promise对象
    if (error.code === 'ERR_BAD_REQUEST') {
      Promise.resolve({});
    } else {
      return Promise.reject(error);
    }
  });
  return request.axiosRequest(instance, method, url, params, headers, thenCall);
}

本地代理地址配置(仅在开发时生效)

devServer: {
  proxy: {
    '/api/*': {
      target: 'https://xxx.xxxx.com/',
      changeOrigin: true,
      pathRewrite: {
        '^/api': '/'
      }
    }
  }
},
封装axiosRequest网络请求核心组件(axios-request.js)

网络请求post请求参数梳理

if (type == "post" || type == "POST") {
  //如果文件上传则创建FormData对象再将数据赋值给data,否则直接将参数赋值给data对象
  if (params && headers["Content-Type"] == "multipart/form-data") {
    let formData = new FormData();
    for (let field in params) {
      if (field == "file") {
        let file = params[field];
        formData.append('file', file, file.name || '');
      } else {
        formData.append(field, params[field]);
      }
    }
    requestParams["data"] = formData;
  } else {
    requestParams["data"] = params;
  }
}

对delete、put请求参数处理,自动将请求参数转成query方式,这样做在实际调用时可以不需要考虑具体传参方式

if (type == "delete" || type == "DELETE" || type == "put" || type == "PUT") {
  //如果是delete和put自动将请求参数转成query方式,这样做在实际调用时可以不需要考虑具体传参方式
  for (let paramsKey in params) {
    url = updateQueryStringParameter(url, paramsKey, params[paramsKey]);
  }
}

function updateQueryStringParameter(uri, key, value) {
  let re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  let separator = uri.indexOf('?') !== -1 ? "&" : "?";
  if (uri.match(re)) {
    return uri.replace(re, '$1' + key + "=" + value + '$2');
  } else {
    return uri + separator + key + "=" + value;
  }
}

axios网络统一请求
这里除了put其它都以能用的方式axios.create({})处理,因为put不支持接收axios.create({“method”:“PUT”})方式

if (type == "put" || type == "PUT") {
  instance.put(url, requestParams).then(res => {
    //这里处理你的返回数据,可以回调抛出去,下面给出完整示例中带有数据响应处理handleResult
    // that.handleResult(true, res, resolve, reject, thenCall);
  }).catch(res => {
    //这里处理你的异常数据,可以回调抛出去,下面给出完整示例中带有数据响应处理handleResult
    // that.handleResult(false, res, resolve, reject, thenCall);
  });
} else {
  requestParams["method"] = type;
  requestParams["url"] = url;
  instance(requestParams).then(res => {
    //这里处理你的返回数据,可以回调抛出去,下面给出完整示例中带有数据响应处理handleResult
    // that.handleResult(true, res, resolve, reject, thenCall);
  }).catch(res => {
    //这里处理你的异常数据,可以回调抛出去,下面给出完整示例中带有数据响应处理handleResult
    // that.handleResult(false, res, resolve, reject, thenCall);
  });
}

请求插件axios-request.js完整代码

function updateQueryStringParameter(uri, key, value) {
  let re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  let separator = uri.indexOf('?') !== -1 ? "&" : "?";
  if (uri.match(re)) {
    return uri.replace(re, '$1' + key + "=" + value + '$2');
  } else {
    return uri + separator + key + "=" + value;
  }
}

export default {
  request: function (axiosInstance, type = "", url = "", headers = {}, params = {}, requestHandle, thenCall) {
    if (type == "post" || type == "POST") {
      //当post请求时以json方式提交数据
      if (!headers["Content-Type"]) {
        headers["Content-Type"] = "application/json;charset=utf-8";
      }
    }
    //将请求包装一个Promise立即返回
    return new Promise((resolve, reject) => {
      if (requestHandle) {
        requestHandle(axiosInstance, url, params, headers, resolve, reject, thenCall);
      }
    });
  },
  axiosRequest: function (axiosInstance, type = '', url = '', params = {}, headers = {}, thenCall) {
    let that = this;
    return that.request(axiosInstance, type, url, headers, params, function (instance, url, params, headers, resolve, reject, thenCall) {
      let requestParams = {
        headers: headers
      };
      if (type == "post" || type == "POST") {
        //如果文件上传则创建FormData对象再将数据赋值给data,否则直接将参数赋值给data对象
        if (params && headers["Content-Type"] == "multipart/form-data") {
          let formData = new FormData();
          for (let field in params) {
            if (field == "file") {
              let file = params[field];
              formData.append('file', file, file.name || '');
            } else {
              formData.append(field, params[field]);
            }
          }
          requestParams["data"] = formData;
        } else {
          requestParams["data"] = params;
        }
      } else if (type == "delete" || type == "DELETE" || type == "put" || type == "PUT") {
        //如果是delete和put自动将请求参数转成query方式,这样做在实际调用时可以不需要考虑具体传参方式
        for (let paramsKey in params) {
          url = updateQueryStringParameter(url, paramsKey, params[paramsKey]);
        }
      } else {
        //否则直接将参数赋值给请求对象
        requestParams["params"] = params;
      }
      //这里除了put其它都以能用的方式axios.create({})处理,因为put不支持接收axios.create({"method":"PUT"})方式
      if (type == "put" || type == "PUT") {
        instance.put(url, requestParams).then(res => {
          that.handleResult(true, res, resolve, reject, thenCall);
        }).catch(res => {
          that.handleResult(false, res, resolve, reject, thenCall);
        });
      } else {
        requestParams["method"] = type;
        requestParams["url"] = url;
        instance(requestParams).then(res => {
          that.handleResult(true, res, resolve, reject, thenCall);
        }).catch(res => {
          that.handleResult(false, res, resolve, reject, thenCall);
        });
      }
    }, thenCall);
  }
}
设置全局拦截器

通过全局请求拦截器,可以在每个请求发送前执行一些固定的操作,比如添加认证信息(如Token)、设置请求头、统一错误处理等。这有助于减少重复代码,并保持应用程序的一致性。

import Vue from 'vue';
import VueAxios from 'vue-axios';
import axios from 'axios';

Vue.use(VueAxios, axios);

// 设置统一的url
axios.defaults.baseURL = "/api";

axios.interceptors.request.use((config) => {
  // 这里可以添加公共头信息
  return config;
}, function (error) {
  return Promise.reject(error);
});
请求示例
await axiosapi('get', '/user/login', {
"user":"admin",
"password":"123456",
....
});

错误返回数据结构

{
    "code": xxx, //请求状态码
    "msg": "请求状态消息"
}

成功返回数据结构

{
    "code": 0, //0-成功
    "msg": "success",
    "data":{xxx} //响应数据信息
}

哦了,感谢你看到这里也请动动您的鼠标和小手关注一下我吧,同时也期待您在评论区提出建议,可以使我创作更优质的内容。


原文地址:https://blog.csdn.net/smart_ljh/article/details/145216840

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!