Vue3+TS版本Uniapp:封装uni.request请求配置

作者:前端小王hs

阿里云社区博客专家/清华大学出版社签约作者✍/CSDN百万访问博主/B站千粉前端up主

封装请求配置项

封装拦截器

uniapp的封装逻辑不同于Vue3项目中直接使用axios.create()方法创建实例(在create方法中写入请求的地址、请求头、超时等内容),代码如下:

ts 复制代码
const instance = axios.create({
	// 后端url地址
	baseURL: import.meta.env.VITE_API_BASEURL,
	timeout: 6000, //设置超时
	headers: {
		'Content-Type': 'application/x-www-form-urlencoded'
	}
});

PS:上述代码来自博主在B站的Vue3全家桶+MySQL+Express全栈实战项目源码

uniapp中,需要使用到一个官方的APIuni.addInterceptor(STRING, OBJECT),这是一个用于拦截 作用的API,在规范开发的过程中,会在请求之前为请求的内容拼接url、超时和请求头等信息,这一点在官方文档API的基础拦截器一文中详细的示例,代码如下:

ts 复制代码
uni.addInterceptor('request', {
  invoke(args) {
    // request 触发前拼接 url 
    args.url = 'https://www.example.com/'+args.url
  },
  success(args) {
    // 请求成功后,修改code值为1
    args.data.code = 1
  }, 
  fail(err) {
    console.log('interceptor-fail',err)
  }, 
  complete(res) {
    console.log('interceptor-complete',res)
  }
})

所以可以封装一个拦截器的配置项,为所有的uni.request添加请求前置信息,代码如下:

ts 复制代码
const baseURL = import.meta.env.VITE_API_BASEURL
// 添加拦截器
const httpInterceptor = {
  // 拦截前触发
  invoke(options: UniApp.RequestOptions) {
    // 假设开头为非http的请求url地址
    if (!options.url.startsWith('http')) {
      options.url = baseURL + options.url
    }
    // 请求超时
    options.timeout = 6000
    options.header = {
      ...options.header,
      // 自定义标识符,用于后端区分app、后台或其他渠道请求
      'source-client': 'app',
    }
    // 添加 token 请求头标识
    const token = uni.getStorage('token')
    if (token) {
      options.header.Authorization = token
    }
  },
}

uni.addInterceptor('request', httpInterceptor)

这是一段万能的uniapp封装拦截器代码,读者可收藏 此文章粘贴即用,下同

封装uni.request

这里的封装,参考了axios返回promise对象的实现逻辑,在接口中return一个promise对象,便于在实际环境中更好的获取数据以及进一步处理数据,代码如下:

ts 复制代码
type Data<T> = {
	// 后端返回的通用响应结构
	statusCode: string
	msg: string
	result: T
}
// UniApp.RequestOptions为配置网络请求的选项
// 这里使用了泛型,便于自定义响应结构
export const http = <T>(options: UniApp.RequestOptions) => {  
  return new Promise<Data<T>>((resolve, reject) => {  
    uni.request({  
      // 拦截器配置内容
      ...options,
      success(res) {
      	// 成功响应
        handleResponse(res, resolve, reject);
      }, 
      fail(err) { 
        handleError(err, reject);
      },  
    });  
  };  
};  

// resolve和reject不返回任何值,但通知promise更改状态
const handleResponse = <T>(res: any, resolve: (value: Data<T>) => void, reject: (reason?: any) => void) => {
  // 分离了验证状态码逻辑
  if (isSuccessStatusCode(res.statusCode)) {  
    resolve(res.data as Data<T>);
  // 登录失败
  } else if (res.statusCode === 401) {  
    // 假设 clearUserInfo 是清除用户信息的函数 
    clearUserInfo();
    // 跳转至登录页面
    uni.navigateTo({ url: '/pages/login/index' });
    reject(res);
  } else {
  	// 分离了报错状态码逻辑
    showErrorToast(res.data as Data<T>); 
    reject(res);
  }  
};  
  
const handleError = (err: any, reject: (reason?: any) => void) => {
  uni.showToast({
    icon: 'none',  
    title: '网络可能开小差了~',  
  });
  reject(err);
};
  
const isSuccessStatusCode = (statusCode: number) => {
  return statusCode >= 200 && statusCode < 300;
};
  
const showErrorToast = <T>(data: Data<T>) => {
  uni.showToast({
    icon: 'none',
    title: data.msg || '请求错误',
  });
};

关于RequestOptions更多的信息,可以对其ctrl+点击查看内置的接口信息,如下图所示:

相关推荐
前端_学习之路21 分钟前
React--Fiber 架构
前端·react.js·架构
coderlin_23 分钟前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说38 分钟前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409191 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding1 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
2501_915918411 小时前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview
布兰妮甜1 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui
SevgiliD1 小时前
el-button传入icon用法可能会出现的问题
前端·javascript·vue.js
我在北京coding1 小时前
Element-Plus-全局自动引入图标组件,无需每次import
前端·javascript·vue.js
鱼 空1 小时前
解决el-table右下角被挡住部分
javascript·vue.js·elementui