taro框架是一个跨端兼容的开发框架,自带了请求相关的API,虽然灵活,但是封装程度并不高,会导致比较多的代码冗余,因此封装了一个请求相关的工具
思路如下:
1、请求和响应需要拦截器,针对不同的情况做不同的处理
2、开发中分为开发,测试,生成环境,要根据不同的环境做适配
3、请求分为get、post、delete、put,调用不同的接口还是有点麻烦的,能不能封装一个工具只 调一个接口,然后自动做适配呢?
实现如下:
1、在src下创建network文件夹,这里存放请求封装相关的文件
2、创建baseUrl.ts 根据不同的环境读取不同的地址
const getBaseUrl = () => {
let BASE_URL = '';
if (process.env.NODE_ENV === 'development') {
//开发环境 - 根据请求不同返回不同的BASE_URL
BASE_URL = 'https://cn.vuejs.org/'
} else {
// 生产环境
BASE_URL = 'https://cn.vuejs.org/'
}
return BASE_URL
}
export default getBaseUrl;
3、创建config.ts,定义响应的状态码
export const HTTP_STATUS = {
SUCCESS: 200,
CREATED: 201,
ACCEPTED: 202,
CLIENT_ERROR: 400,
AUTHENTICATE: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
SERVER_ERROR: 500,
BAD_GATEWAY: 502,
SERVICE_UNAVAILABLE: 503,
GATEWAY_TIMEOUT: 504
}
4、定义utils.ts,当需要登录才可以请求时,维护处理逻辑
import Taro from "@tarojs/taro";
/**
* @description 获取当前页url
*/
export const getCurrentPageUrl = () => {
let pages = Taro.getCurrentPages()
let currentPage = pages[pages.length - 1]
let url = currentPage.route
return url
}
export const pageToLogin = () => {
let path = getCurrentPageUrl()
Taro.clearStorage()
if (!path.includes('login')) {
Taro.reLaunch({
url: "/pages/login/login"
});
}
}
5、定义拦截器interceptors.ts
import Taro from "@tarojs/taro"
import { pageToLogin } from "./utils"
import { HTTP_STATUS } from './config'
const customInterceptor = (chain) => {
const requestParams = chain.requestParams
Taro.showLoading({
title: '加载中',
})
return chain.proceed(requestParams).then(res => {
Taro.hideLoading()
// 只要请求成功,不管返回什么状态码,都走这个回调
if (res.statusCode === HTTP_STATUS.NOT_FOUND) {
return Promise.reject({ desc: '请求资源不存在' })
} else if (res.statusCode === HTTP_STATUS.BAD_GATEWAY) {
return Promise.reject({ desc: "服务端出现了问题" })
} else if (res.statusCode === HTTP_STATUS.FORBIDDEN) {
Taro.setStorageSync("Authorization", "")
pageToLogin()
// TODO 根据自身业务修改
return Promise.reject({ desc: "没有权限访问" });
} else if (res.statusCode === HTTP_STATUS.AUTHENTICATE) {
Taro.setStorageSync("Authorization", "")
pageToLogin()
return Promise.reject({ desc: "需要鉴权" })
} else if (res.statusCode === HTTP_STATUS.SERVER_ERROR) {
return Promise.reject({ desc: "服务器错误" });
} else if (res.statusCode === HTTP_STATUS.SUCCESS) {
return res.data
// if (res.data.code === 0) {
// return res.data
// } else if (res.data.code == '-100') {
// //非法登录
// pageToLogin()
// }
// else {
// return Promise.reject(res.data)
// }
}
}).catch(error=> {
Taro.hideLoading()
console.error(error)
return Promise.reject(error)
})
}
// Taro 提供了两个内置拦截器
// logInterceptor - 用于打印请求的相关信息
// timeoutInterceptor - 在请求超时时抛出错误。
// const interceptors = [customInterceptor, Taro.interceptors.logInterceptor]
const interceptors = [customInterceptor]
export default interceptors
6、定义request.ts,适配taro的请求API
import Taro from '@tarojs/taro'
import getBaseUrl from './baseUrl'
import interceptors from './interceptors'
//添加拦截器
interceptors.forEach(interceptorItem => Taro.addInterceptor(interceptorItem))
const request=function axios(params) {
let { url, data,method,headers} = params;
const BASE_URL = getBaseUrl();
// let contentType = "application/x-www-form-urlencoded";
let contentType = "application/json;charset=UTF-8";
contentType = headers?.contentType || contentType;
const option = {
url: BASE_URL + url, //地址
data: data, //传参
method: method, //请求方式
timeout:50000, // 超时时间
header: { //请求头
'content-type': contentType,
'Authorization':Taro.getStorageSync('Authorization')
}
};
return Taro.request(option);
}
export default request
7、以上关于请求工具就封装好了,接下来就是使用了,我向来不太赞成后台的路径等相关API信息写在视图文件中,比较乱,而且不好维护。所以
在src下创建一个api目录,创建demo.ts(这里仅仅是一个示例,仅供参考)
import request from '@/network/request'
const attractInvestmentApi = {
baidu: 'api/composition-api-setup.html#usage-with-render-functions',
}
export function taroTest (parameter) {
return request({
url: attractInvestmentApi.baidu,
method: 'get',
data: parameter,
// headers: {
// 'contentType': 'application/json'
// }
})
}
8、实际业务中调用后端api(这里仅仅是一个示例,仅供参考)