微信小程序中使用axios封装网络请求并配置拦截器,实现request发起网络请求和uploadFile上传文件到服务器

390 阅读5分钟

使用步骤

1. 下载所需依赖包并构建npm

  • npm i axios@0.18.1:下载axios包。适配器对axios版本强制要求最高只支持0.19.x版本。
  • npm i axios-miniprogram-adapter:axios的微信小程序适配器。官方文档

2. 导入axios和适配器

  • import axios from "axios"
  • import mpAdapter from "axios-miniprogram-adapter"

3. 使用适配器

  • axios.defaults.adapter = mpAdapter

4. 创建axios实例instance

  • baseURL:根地址,也就是服务器地址。后面所有通过instance发起的请求都会自动拼接。
  • timeout:超时时间,单位ms。
  • headers:公共请求头。例如:{'Content-Type': 'application/json;charset=UTF-8',key:value}
const instance = axios.create({
  baseURL: "https://tzof.net:217",
  timeout: 10000,
});

5. 配置请求拦截器instance.interceptors.request.use()

请求拦截器的作用是让在发送请求之前做些什么。如增加公共请求头等。

  • 第一个函数形参config表示请求体的配置,其中有headersdata等信息。函数内可以修改config的配置,将修改后的配置信息return返回出去,如不返回配置信息会阻断接口的发送。
  • 第二个函数形参error表示错误信息,函数内可以填写如果请求报错需要做的处理。
instance.interceptors.request.use(
  function (config) {
    const storageToken = wx.getStorageSync("token");
    const token = "Bearer " + storageToken;
    config.headers.Authorization = token;
    return config;
  },
  function (error) {
    console.error("error", error);
    return Promise.reject(error);
  }
);

6. 配置响应拦截器instance.interceptors.response.use()

响应拦截器的作用是接收到后端返回的内容响应报文后需要做些什么。

  • 第一个函数形参response表示后端返回的内容响应报文,其中有headersstatusdata等信息。函数内可以修改response的内容,将修改后的响应报文return返回出去,如不返回响应报文会阻断接口的接收。
  • 第二个函数形参error表示错误信息,函数内可以填写如果请求报错需要做的处理。
instance.interceptors.response.use(
  function (response) {
    return response;
  },
  function (error) {
    console.error("error", error);
    return Promise.reject(error);
  }
);

7. 封装公共请求方法

用于接收参数:请求方式、接口url、参数、请求体格式,并使用instance发起请求并做处理。

  • method:请求的方式如GETPOSTDELETEUPDATE
  • url:请求的接口url。在url之前会自动拼接创建axios实例时设置的baseURL
  • params:需要传给后端的参数。
  • formatType:请求体格式,会设置请求头Content-Type
    urlencoded表示application/x-www-form-urlencodedjson表示application/json
  • instance(axiosParams):发送请求。instance.request()可以发送请求,直接用axios实例也行。
    instance.then(res)表示接口成功的回调函数,res形参表示后端返回的响应体,res.data是后端返回的响应内容。可以在返回成功后判断code对不同情况做出处理,如token失效过期时候则转跳login页面。resolve(res.data)的参数是方法成功时返回给then()的。reject(err)的参数是方法失败时返回给catch()的。
export function ajaxRequest(method, url, params, formatType) {
  // 返回一个promise对象 引用的地方可以使用.then或者await获取res数据
  return new Promise((resolve, reject) => {
    // method 请求方式
    // url 请求地址
    let axiosParams = {
      method,
      url,
    };
    // params 是GET、DELETE请求的时候用的请求参数 会变成字符串拼接到路由上 /users?page=1&limit=10
    if (method === "GET" || method === "DELETE") {
      axiosParams.params = params;
    }
    // data 是POST、PUT、PATCH请求的时候用的请求体 会变成键值对模式 {"username":"tzof","age":"18"}
    // headers 请求头信息如Content-Type、Authorization等。
    else {
      axiosParams.data = params;
      if (formatType == "urlencoded") {
        axiosParams.headers = {
          "Content-Type": "application/x-www-form-urlencoded",
        };
      } else if (formatType == "json") {
        axiosParams.headers = {
          "Content-Type": "application/json",
        };
      }
    }
    // instance.request发送请求,不加request也可以,也可以直接用创建的axios实例对象发送
    instance(axiosParams)
      .then((res) => {
        // 没有提供token、token失效或者过期  403 Forbidden禁止进入的
        if (res.data.code == 403) {
          wx.removeStorageSync("token");
          wx.removeStorageSync("openId");
          wx.showToast({
            title: res.data.msg,
            icon: "error",
            duration: 950,
          });
          setTimeout(() => {
            wx.navigateTo({
              url: "/pages/login/login",
            });
          }, 1000);
        }
        resolve(res.data);
      })
      .catch((err) => {
        console.log(err);
        reject(err);
      });
  });
}
export function axiosWx(method, url, params) {
  return ajaxRequest(method, url, params, "urlencoded");
}

export function axiosWxJson(method, url, params) {
  return ajaxRequest(method, url, params, "json");
}

8. 封装文件上传方法

使用wx官方wx.uploadFile()实现文件上传,删除无用参数并增加promise风格返回便于异步操作。注意wx.uploadFile()成功后返回的数据是JSON字符串格式,需要用JSON.parse(res.data)转换成json对象。

export function uploadFile(url, params) {
  const filePath = params.file;
  delete params.file;
  return new Promise((resolve, reject) => {
    wx.uploadFile({
      filePath,
      name: "file",
      url: instance.defaults.baseURL + url,
      formData: params,
      header: {
        authorization: "Bearer " + wx.getStorageSync("token"),
      },
      success: (res) => {
        resolve(JSON.parse(res.data));
      },
      fail: (err) => {
        reject(err);
      },
    });
  });
}

完整代码

import axios from "axios";
// 特定于微信小程序的适配器
import mpAdapter from "axios-miniprogram-adapter";
// 使用适配器
axios.defaults.adapter = mpAdapter;
// 创建一个axios实例
const instance = axios.create({
  baseURL: "https://tzof.net:217",
  timeout: 10000,
});

// 添加请求拦截器
instance.interceptors.request.use(
  function (config) {
    // 在发送请求之前做些什么
    // Bearer令牌是一种常用的认证机制,特别是在 OAuth 2.0 授权框架中。尽管 JWT 本身是一种独立的令牌格式,但在实际应用中,通常会在 HTTP 请求头中使用 Bearer 方式来携带 JWT。
    // Bearer JWT Bearer表示后面的令牌是一种“持有者令牌”(bearer token)。这意味着任何持有该令牌的人都被视为合法的请求者。
    const storageToken = wx.getStorageSync("token");
    const token = "Bearer " + storageToken;
    config.headers.Authorization = token;
    return config;
  },
  function (error) {
    // 对请求错误做些什么
    console.error("error", error);
    return Promise.reject(error);
  }
);

// 添加响应拦截器
instance.interceptors.response.use(
  function (response) {
    // 对响应数据做点什么
    return response;
  },
  function (error) {
    // 对响应错误做点什么
    console.error("error", error);
    return Promise.reject(error);
  }
);
export function ajaxRequest(method, url, params, formatType) {
  // 返回一个promise对象 引用的地方可以使用.then或者await获取res数据
  return new Promise((resolve, reject) => {
    // method 请求方式
    // url 请求地址
    let axiosParams = {
      method,
      url,
    };
    // params 是GET、DELETE请求的时候用的请求参数 会变成字符串拼接到路由上 /users?page=1&limit=10
    if (method === "GET" || method === "DELETE") {
      axiosParams.params = params;
    }
    // data 是POST、PUT、PATCH请求的时候用的请求体 会变成键值对模式 {"username":"tzof","age":"18"}
    // headers 请求头信息如Content-Type、Authorization等。
    else {
      axiosParams.data = params;
      if (formatType == "urlencoded") {
        axiosParams.headers = {
          "Content-Type": "application/x-www-form-urlencoded",
        };
      } else if (formatType == "json") {
        axiosParams.headers = {
          "Content-Type": "application/json",
        };
      }
    }
    // instance.request发送请求,不加request也可以,也可以直接用创建的axios实例对象发送
    instance(axiosParams)
      .then((res) => {
        // 没有提供token、token失效或者过期  403 Forbidden禁止进入的
        if (res.data.code == 403) {
          wx.removeStorageSync("token");
          wx.removeStorageSync("openId");
          wx.showToast({
            title: res.data.msg,
            icon: "error",
            duration: 950,
          });
          setTimeout(() => {
            wx.navigateTo({
              url: "/pages/login/login",
            });
          }, 1000);
        }
        resolve(res.data);
      })
      .catch((err) => {
        console.log(err);
        reject(err);
      });
  });
}
export function axiosWx(method, url, params) {
  return ajaxRequest(method, url, params, "urlencoded");
}

export function axiosWxJson(method, url, params) {
  return ajaxRequest(method, url, params, "json");
}

export function uploadFile(url, params) {
  const filePath = params.file;
  delete params.file;
  return new Promise((resolve, reject) => {
    wx.uploadFile({
      filePath,
      name: "file",
      url: instance.defaults.baseURL + url,
      formData: params,
      header: {
        authorization: "Bearer " + wx.getStorageSync("token"),
      },
      success: (res) => {
        resolve(JSON.parse(res.data));
      },
      fail: (err) => {
        reject(err);
      },
    });
  });
}