大家好,我是Aliom252181,一个佛系且资质平平的前端coder,今天分享下我是如何使用Typescript
封装wx.request
的。
写在前面
本篇文章适合有封装TS版本小程序请求需求的coder,通过本篇阅读,你将会了解到:
- TS代码提示;
- 单例模式;
- 每个接口都可以灵活配置请求头、超时时间等;
- 取消原生嵌套地狱写法,更符合阅读逻辑。
微信小程序自带的wx.request
请求方式使用方式如下:
wx.request({
url: 'http://host/api/key', //请求的接口地址
method:"get", //http请求数据的方式
data:{name:'',age:''}, //请求的参数,如name和id
//请求头设置,根据需要自己设置
header:{
'content-type':"application/json"
},
//请求成功时的回调函数
success(res){
console.log(res);
},
//请求失败的回调函数
fail(msg){
console.log(msg);
}
})
如果不封装的话,每次使用请求都会造成大段重复代码占用代码区,对阅读极其不利,也降低了开发效率,为了解决这个问题,一起来开启封装之旅吧。
基础类型封装
首先我们要先定义一些我们需要的类型,例如请求参数类型,返回数据类型,还有一些枚举类型,现在开始封装:
封装HTTP请求配置
// HTTP请求方法枚举
export enum HttpMethod {
GET,
POST
}
// HTTP请求配置
interface RequestConfig {
/** API路径 */
url?: string
/** Method类型 */
method?: HttpMethod
/** 接口返回数据 */
data?: any
/** 无TOKEN触发异常捕获时,是否执行异常逻辑 */
needToken?: boolean
/** Header头部 */
header?: object
}
其中needToken
是我们的业务逻辑,此参数主要作用于一些需要权限接口,如果我们不想让他在request
层级触发我们的逻辑,例如不想触发登录验证,就可以在接下来处理返回code时使用。
封装请求返回数据类型
// 继承中间类型,data声明为any
interface AnyResult extends WechatMiniprogram.RequestSuccessCallbackResult {
data: any
}
// 从中间类型继承一个泛型接口,data声明为泛型
interface SpecResult<T> extends AnyResult {
data: T
}
// 声明业务数据类型
export interface MyAwesomeData {
code: number
msg: string
data: any
}
这一步是定义返回参的类型,我们希望最终的返回结果为{code,msg,data}
,便于我们的使用。其中注意WechatMiniprogram
是微信提供的类型,需要大家在TS小程序项目内使用,也可以使用NPM包miniprogram-api-typings
来作为校验,如果是后者,要注意在tsconfig.json
的typeRoots
字段内设置此包地址,例如:
"typeRoots": [
"./node_modules/miniprogram-api-typings"
],
环境配置
除了正式环境,大家的日常开发中免不了要进行多环境切换,这里写成配置,方便开发使用。
首先新建env.ts文件作为环境配置中心,这里我已常用的三环境为例,大家自行扩展。
// env.ts
let envs = {
dev: {
host: 'http://192.168.0.1:20087/',
imgHost: 'http://192.168.0.2:20087/'
},
test:{
host: 'http://192.168.0.1:20086/',
imgHost: 'http://192.168.0.2:20086/'
},
prod: {
host: 'https://XXXXX.com/',
imgHost: 'http://image.XXXXX.com/'
},
}
module.exports = envs
接下来新建config.ts文件作为小程序配置中心,用来控制环境切换和其他配置。
// config.ts
// 基础共同的配置
let baseConfig = {
// 小程序appid
appid: '……',
// 环境
ENV:'dev'
}
//环境文件
let envConfig = require('./env')
// 合并配置
let config = Object.assign(baseConfig, envConfig[baseConfig.ENV])
// 导出配置
module.exports = config
核心代码封装
恭喜你,看到这里,你已经完成了所有封装的前期准备工作,那么我们开始正式封装。
定义核心请求类HttpRequest
这里我们使用单例模式定义此核心类,好处有三:
- 单例模式可以确保所有对象都访问唯一实例;
- 因为类控制了实例化过程,所以类可以灵活更改实例化过程;
- 因为只有一个实例,所以减少内存开支和系统的性能开销。
虽然我很赞同那句:最好的注释就是没有注释",但是这在工具类里显然不生效,工具类的作用是让使用的人快速完成某项活动,而不是让他惊叹三连。所以该有的注释还是要有的,如果大家对于注释感兴趣的人数足够多,我会开一期如何写注释的文章。
export class HttpRequest {
private static instance: HttpRequest
private constructor() {}
/** 请求函数(单例模式)
*
* **注意:**
* 1. 处理请求的函数记得使用`async/await`
* 2. `method`需使用`HttpMethod`枚举类,切勿自行定义
*
* **示例代码**
* ```js
HttpRequest.getInstance().request({
url: '/Api',
method: HttpMethod.GET
})
* ```
*/
public static getInstance(): HttpRequest {
if (!this.instance) {
this.instance = new HttpRequest()
}
return this.instance
}
}
写到这里,单例模式就完成了,那么现在我们需要实现url的拼接。
处理url
在HttpRequest
中定义getApiAppName
方法。此方法是兼容全路径写法的请求,在实际开发中,可以有一些非环境配置中心的请求需要处理,所以这里做一个兼容处理,同时也拼接好了全路径。
// 处理url 兼容全路径
private getApiAppName(url: string | undefined) {
if (!url) {
return
}
if (typeof url == 'string' && url.indexOf('http') >= 0) {
return url
}
return `${Config.host}${url}`
}
处理异常
在HttpRequest
中定义handerErrorStatus
方法。此方法是用来处理后端异常状态码。
// 处理后端异常状态码
private handerErrorStatus(statusCode: number, requestConfig: RequestConfig) {
if (statusCode == 502 || statusCode == 503) {
if (requestConfig.needToken) {
wx.showToast({
title: '服务器开小差',
icon: 'none'
})
}
return true
}
return false
}
定义核心方法request
在HttpRequest
中引入配置文件。
// 引入配置文件
const Config = require('../config/config')
接下来在HttpRequest
中定义核心方法request
,这里在处理状态码的时候采用的是if/else
写法,如果大家业务里有更多的逻辑可以外面把规则定义成Map
,然后内部引用规则,方便理解和阅读。
再次强调,一个好的代码是可以别人看懂而不是只有自己能看到,尤其是工具类方法,更要要降低理解门槛和使用门槛。
public request(requestConfig: RequestConfig): Promise<SpecResult<MyAwesomeData>> {
let _this = this
//url处理
requestConfig.url = this.getApiAppName(requestConfig.url)
return new Promise((resolve, reject) => {
// 默认header
let header = {
'content-type': 'application/json'
}
wx.request({
method: requestConfig.method === HttpMethod.GET ? 'GET' : 'POST',
url: `${requestConfig.url}`,
data: requestConfig.data,
header: Object.assign(header, requestConfig?.header),
success: async function (res: SpecResult<MyAwesomeData>) {
console.log('发送返回:', res) //res:{cookies, data, header, statusCode}
if (_this.handerErrorStatus(res.statusCode, requestConfig)) {
reject('失败了')
} else {
// 200状态码请求正常
if (res.statusCode == 200) {
if ([401, 402, 403, 405, 407, 408].indexOf(res.data.code) != -1 && requestConfig.needToken) {
//……
}
} else {
//非200状态码(排除handerErrorStatus特殊处理过的状态码)-数据处理
res.data = { code: res.statusCode || -404, msg: '服务找不到', data:res.data }
}
}
resolve(res)
},
fail: err => reject(err)
})
})
}
恭喜你,到这里,封装已经完美结束了,那么我们一起来看下如何使用吧。
使用
- 在需要使用的文件内引入
request
。
import { HttpMethod, HttpRequest } from '/resources/utils/request';
- 使用
async/await
接受返回值。
const res = await HttpRequest.getInstance().request({
url: 'serviceProduct/showcase/getShowcase',
method: HttpMethod.GET
})
- 可以开始业务逻辑啦!
写在最后
小程序这个系列我还会继续更新,敬请期待~文章来源:https://www.toymoban.com/news/detail-491455.html
本篇文章到这里就结束了,如果文章对你有用,可以三连支持一下,如果文章中有错误或者说你有更好的见解,欢迎指正~文章来源地址https://www.toymoban.com/news/detail-491455.html
到了这里,关于小程序开发指南-TS封装wx.request的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!