每个人都要有封装思维:Taro Es6承诺构建微信小程序的简单全局请求方法
无论是app、applet还是其他端,在交互中请求无处不在。
一个优秀的打包类可以让你的开发效率事半功倍,所以打包逻辑非常重要。当然我也是菜鸟,根据自己的想法写了一些包装方法。一方面想改正自己的缺点,希望路过的神仙给我指正。另一方面,我想为初学者打开一扇善于包装思维的大门,然后进入前知。
空气污染指数:cnodejs.org/api/v1
Ts:简单的类型声明、接口等。
Es6:结构分配、扩展操作、承诺、导出等。
芋头:上课反应,小程序基础知识等。
1.梳理Taro的请求 Taro.request,实现最简易的请求方法
从“@ Tarojs/Taro”//回调函数中导入Taro调用Dorequstation(){ Taro . request({ URL : ' '),Data : {},Succe:res={ },Fail3360err={},complete : Info={ })}//promise调用Function Dorequestaction(){ Taro . request({ URL 3360 ' ',Data : {},Header: { }然后(RES={})。Catch (err={})。最后(()={})}复制代码。优缺点就不多介绍了。我们将使用承诺的请求方法。
2.梳理会用到的请求结构,以及定义的文件分类:
接口地址,也称为url,存储在api.ts文件中。request方法,也称为我们封装的方法,我们存储在request.ts文件中的接口类型,我们声明数据类型的文件,我们存储在inter.d.ts文件中的配置文件,常用的全局请求域名,其他固定参数等。这里我们只是一个简单的例子,所以不需要。如有需要,请配置文件名函数api.ts存储接口地址,统一请求域名前缀request.ts封装公共请求方法,调用方法的声明文件设置inter.d.tsts,主要存储返回值类型、请求参数类型等。
3.接入promise声明自己的方法并返回自己的promise请求对象
.我会尽量在这里写es6,让大家在以后的项目开发中可以更流畅的使用。当然,请结合我自己项目的实际情况。在下面输入知识点:
请求加载是真的吗?隐藏加载: ' '加载加载层是否打开伪装文字参数可以自定义请求是否失败弹出我们的错误消息url。使用自定义接口从“@ tarojs/Taro”//导入Taro暂时考虑req的属性,const dorequestation=(req)={返回新承诺((解析,拒绝)={ if(req . loading)Taro . show loading({ title 3360 req . title?Req.title :“正在加载数据.”})taro . request({ URL :/http(s?):\/\//.测试(req.url)?Req.url : ' ',//Leave方法3360' post ',数据: {}暂时。标头: { ' content-type ' : ' application/x-www-form-URL encode ' } })。然后(RES={})。catch(err={//错误提示}) })。最后(()={ if(req . loading)taro . hide loading()})})} }复制代码
4.分离请求参数并使用ts声明传入值与类型
1。分离使用的参数。2.给每个参数一个默认值,如果没有传递,就用默认值替换。3.用ts声明参数类型。
导出请求基{URL :字符串,//字符串方法: 'POST' | 'GET ',//常规请求方法,根据
项目要求添加 data: any, // 每次的参数都是不固定的,因此我们暂时不声明数据类型 header: RequestHeader, // 下面的requestheader类型, loading: boolean, // 请求是否开启loading层 mask: boolean, //开启loading层的情况下是否不能点击,全屏遮罩 title: string, //开启loading层的提示内容 failToast: boolean //如果请求是否,我是否直接弹出我的提示}export interface RequestHeader { 'content-type': string // 表示content-type类型必须声明}复制代码上面的header,我重新定义了一个接口来声明类型,是为了更方便的去管理这个数据,试想如果我们平时需要将用户的token带入到header里面,那么我们就会在RequestHeader中在声明一个token字段。
所谓的接口也就相当于我们这个数据里面有什么字段,字段是什么类型。
所以,我们在header中在加入token字段,实际项目中,可能还会带入加密串,时间,以及其他的辅助验证字段,这里只为了大家方便开发做出示例,实际还需看项目声明。
特殊提醒:ts是可以不加逗号的
export interface RequestHeader { 'content-type': string // 表示content-type类型必须声明 token: string}复制代码
声明我们的默认参数,在用户没有参数传入的情况下,将会使用我们的默认参数来辅助请求。
// 使用默认参数,当数据不传入指定字段时替代const NormalRquestData: RequestBase = { url: api.DOMAIN, // 默认请求地址 method: 'GET', // 默认get请求 header : { // 默认使用的header头 "content-type": 'application/x-www-form-urlencoded', token: '' }, data: {}, // 默认没有参数,传入空对象 loading: true, //默认开启loading层 mask: true, //请求时不需要点击 title: '数据加载中', //loading提示文字 failToast: false // 一般我们会处理相应业务逻辑,就不直接提示阻断流程}复制代码
思考问题,我们如果每次动态 带上我们token? 用户刚开始进入小程序,这时可能是没有授权,后面授权了我们要及时更新token来达到用户交互目的 这时我们可以将header提出,当然我一般会在我的状态管理中操作,这里做个例子为大家提供思路。
- 将token作为可选字段
- 封装方法每次请求动态提取token
- 方法返回类型为我们定义的RequestHeader类型
// inter.d.tsexport interface RequestHeader { 'content-type': string // 表示content-type类型必须声明 token?: string // token可能不存在,如果存在就是字符串类型}//request.ts 获取header头 返回值是RequestHeader类型const getRequestHeader = (): RequestHeader => { let token: string = Taro.getStorageSync('token') return token ? { "content-type": 'application/x-www-form-urlencoded', token: token } : { "content-type": 'application/x-www-form-urlencoded' }}复制代码
5.在参数某些字段不传入的情况下,我们使用自己的参数字段进行默认填充
思考问题:RequestBase参数都是必传,但是我们的请求的时候参数都是可传,如果我们将其都改为可选参数,这个时候如果我们使用req.title(loading标题)、req.url('请求api地址') 在ts的检测下,这些参数都是可能不存在的,这样我们会写大量判断,那么我们的代码就会变得相当糟糕~!因此我们再声明一个接口用来可选参数的规范。
// 遍历RequestBase中所有key,都改为可选参,这样我们就只管维护RequestBasetype Request = { [K in keyof RequestBase]?: RequestBase[K]}复制代码
改造请求方法,并声明各个类型,使ts更加规范, 将接口类使用inter导入,也将之前的api改成Api统一首字母大写
import Taro from '@tarojs/taro'import * as Api from './api'import * as Inter from './inter.d'// 请求传入reqData参数 返回promise对象 因为全局请求我每次返回的类型都是不一样的,所以我直接anyconst doRequestAction = (reqData: Inter.Request): Promise<any> => { // 将不存在的参数字段使用默认值进行替换 let req: Inter.RequestBase = { ...NormalRquestData, ...reqData } return new Promise((resolve, reject) => { //检测是否开启loading层 是否打开msak if (req.loading) Taro.showLoading({ title: req.title, mask: req.mask }) Taro.request({ url: req.url, //引入我的接口是特殊声明的,所以我就不检测http/https了 method: req.method, data: req.data, header: req.header }) .then(res => { // 大多数请求中 success并不代表成功,需要我们自己检测statusCode来确保 if (res.statusCode === 200) { resolve(res.data) // 成功 } else { // 如果失败 检测是否直接提示信息 if(req.failToast) Taro.showToast({ title: '网络不好,请求失败!' }) reject(res) // 失败 } }) .catch(err => { // 如果失败 检测是否直接提示信息 if (req.failToast) Taro.showToast({ title: '网络不好,请求失败!' }) reject(err) }) .finally(() => { // 请求结束 关闭loading层 if (req.loading) Taro.hideLoading() }) })}复制代码
ok,请求方法写到这里我们暂时只能告一段落了
6.完善api.ts,声明全局域名以及每个接口的定义.
//定义全局请求地址,因为我们用到的地址是https://cnodejs.org/api/v1export const DOMAIN: string = 'https://cnodejs.org/'// 声明获取主题首页接口地址并导出export const topics: string = DOMAIN + 'api/v1/topics'复制代码
7.观察api,声明请求data文件,以及使用请求并返回promise以及返回类型 返回类型:cnodejs.org/api/v1/topi…自己观察我就不截图了。
// 请求主题接口参数类型export interface TOPICSDATA { page: number, tab: 'ask' | 'share' | 'job' | 'good', limit: number, mdrender?: boolean}// 获取主题的接口export interface TOPICS { id: string, author_id: string, tab: string, content: string, title: string, last_reply_at: string, good: boolean, top: boolean, reply_count: number, visit_count: number, create_at: string, author: TOPICSAUTHOR}// 作者的类型export interface TOPICSAUTHOR { loginname: string, avatar_url: string}复制代码
8.自定义获取方法,结合自己的请求方法返回新的promise对象
// 调用封装方法 返回promise对象 得到获取到的数据const getTopics = (data: Inter.TOPICSDATA): Promise<Inter.TOPICS> => { return doRequestAction({ url: Api.topics, data: data })}复制代码
9. 页面内可以调用getTopics方法拿到我们的数据
import { getTopics } from '../../utils/request/request'import { TOPICSDATA } from '../../utils/request/inter'useEffect(()=>{ let data: TOPICSDATA= { page: 1, tab: 'ask', limit: 10 } getTopics(data).then(res=>console.log(res)) },[])复制代码
至此,一个简易的封装就完美的结束了,但是在实际开发中为了自己的便利,我们会封装很多经常使用到的参数,这里只是提供一个封装思维,具体还需要在大家的项目中去思考怎么才能去优化代码。
10.总结
知识点
- es6语法: ...展开运算, 解构赋值, promise
- ts:类型声明, 可选项, type , any类型 ,单个类型定义
- 封装思维,文件拆分
无论是app还是小程序或者其他端,交互中请求无处不在。
一个优秀的封装类,能让你的开发效率事半功倍,所以封装逻辑至关重要,当然我也是个小菜鸟,跟着自己的思路写过一些封装方法,一方面是想不足之处还望路过的大神给予指正,二者是为新手打开一个善于封装思维的大门,下面进入到前置知识。
Api:cnodejs.org/api/v1
Ts: 简易的类型声明、接口等
Es6:结构赋值、扩展运算、promise、export等
Taro:类react,以及小程序基础知识等
1.梳理Taro的请求 Taro.request,实现最简易的请求方法
import Taro from '@tarojs/taro'//回调调用function doRequestAction(){ Taro.request({ url: '', data: {}, header: {}, success: res => {}, fail: err => {}, complete: info => {} })}// promise调用function doRequestAction(){ Taro.request({ url: '', data: {}, header: {} }) .then(res=>{}) .catch(err=>{}) .finally(()=>{})}复制代码
其中利弊不多做介绍,我们将会用到promise的请求方式。
2.梳理会用到的请求结构,以及定义的文件分类:
- 接口地址,也就是我们常说的url,存放于api.ts文件中
- 请求方法,也就是我们封装的方法,我们存放于request.ts文件中
- 接口类型,也就是我们声明数据类型的文件,我们存放于inter.d.ts文件中
- 配置文件,常用的全局请求域名,其他不动参数等,我们这里只是简单的示例因此不需要,如果有需要请大家自行配置
3.接入promise声明自己的方法并返回自己的promise请求对象
我这里尽量写es6写法让大家在今后的项目开发中更加顺畅的使用,当然在自己的项目中请结合实际情况使用,不要盲目的接入一些新的写法。下面进入知识点梳理:
- 请求是否loading,真 ? 结束隐藏loading : ' '
- loading层是否开启mask
- loading文字参数可自定义
- 请求失败是否弹出我们的报错信息
- url在不以http/https的情况下使用自定义接口
import Taro from '@tarojs/taro'// 暂时考虑 req的属性都会传入const doRequestAction = (req) => { return new Promise((resolve, reject) => { if (req.loading) Taro.showLoading({ title: req.title ? req.title : '数据加载中...' }) Taro.request({ url: /^http(s?):\/\//.test(req.url) ? req.url : '', //暂时留空 method: 'POST', data: {}, header: { 'content-type': 'application/x-www-form-urlencoded' } }) .then(res => {}) .catch(err => { //报错提示 }) .finally(() => { if (req.loading) Taro.hideLoading() }) })}复制代码
4.分离请求参数并使用ts声明传入值与类型
1.将使用到的参数进行分离 2.每个参数给出默认值,如果不传人将用默认值代替 3.使用ts声明参数类型
export interface RequestBase { url: string, //字符串 method: 'POST' | 'GET', //常规请求方式,根据项目要求添加 data: any, // 每次的参数都是不固定的,因此我们暂时不声明数据类型 header: RequestHeader, // 下面的requestheader类型, loading: boolean, // 请求是否开启loading层 mask: boolean, //开启loading层的情况下是否不能点击,全屏遮罩 title: string, //开启loading层的提示内容 failToast: boolean //如果请求是否,我是否直接弹出我的提示}export interface RequestHeader { 'content-type': string // 表示content-type类型必须声明}复制代码
上面的header,我重新定义了一个接口来声明类型,是为了更方便的去管理这个数据,试想如果我们平时需要将用户的token带入到header里面,那么我们就会在RequestHeader中在声明一个token字段。
所谓的接口也就相当于我们这个数据里面有什么字段,字段是什么类型。
所以,我们在header中在加入token字段,实际项目中,可能还会带入加密串,时间,以及其他的辅助验证字段,这里只为了大家方便开发做出示例,实际还需看项目声明。
特殊提醒:ts是可以不加逗号的
export interface RequestHeader { 'content-type': string // 表示content-type类型必须声明 token: string}复制代码
声明我们的默认参数,在用户没有参数传入的情况下,将会使用我们的默认参数来辅助请求。
// 使用默认参数,当数据不传入指定字段时替代const NormalRquestData: RequestBase = { url: api.DOMAIN, // 默认请求地址 method: 'GET', // 默认get请求 header : { // 默认使用的header头 "content-type": 'application/x-www-form-urlencoded', token: '' }, data: {}, // 默认没有参数,传入空对象 loading: true, //默认开启loading层 mask: true, //请求时不需要点击 title: '数据加载中', //loading提示文字 failToast: false // 一般我们会处理相应业务逻辑,就不直接提示阻断流程}复制代码
思考问题,我们如果每次动态 带上我们token? 用户刚开始进入小程序,这时可能是没有授权,后面授权了我们要及时更新token来达到用户交互目的 这时我们可以将header提出,当然我一般会在我的状态管理中操作,这里做个例子为大家提供思路。
- 将token作为可选字段
- 封装方法每次请求动态提取token
- 方法返回类型为我们定义的RequestHeader类型
// inter.d.tsexport interface RequestHeader { 'content-type': string // 表示content-type类型必须声明 token?: string // token可能不存在,如果存在就是字符串类型}//request.ts 获取header头 返回值是RequestHeader类型const getRequestHeader = (): RequestHeader => { let token: string = Taro.getStorageSync('token') return token ? { "content-type": 'application/x-www-form-urlencoded', token: token } : { "content-type": 'application/x-www-form-urlencoded' }}复制代码
5.在参数某些字段不传入的情况下,我们使用自己的参数字段进行默认填充
思考问题:RequestBase参数都是必传,但是我们的请求的时候参数都是可传,如果我们将其都改为可选参数,这个时候如果我们使用req.title(loading标题)、req.url('请求api地址') 在ts的检测下,这些参数都是可能不存在的,这样我们会写大量判断,那么我们的代码就会变得相当糟糕~!因此我们再声明一个接口用来可选参数的规范。
// 遍历RequestBase中所有key,都改为可选参,这样我们就只管维护RequestBasetype Request = { [K in keyof RequestBase]?: RequestBase[K]}复制代码
改造请求方法,并声明各个类型,使ts更加规范, 将接口类使用inter导入,也将之前的api改成Api统一首字母大写
import Taro from '@tarojs/taro'import * as Api from './api'import * as Inter from './inter.d'// 请求传入reqData参数 返回promise对象 因为全局请求我每次返回的类型都是不一样的,所以我直接anyconst doRequestAction = (reqData: Inter.Request): Promise<any> => { // 将不存在的参数字段使用默认值进行替换 let req: Inter.RequestBase = { ...NormalRquestData, ...reqData } return new Promise((resolve, reject) => { //检测是否开启loading层 是否打开msak if (req.loading) Taro.showLoading({ title: req.title, mask: req.mask }) Taro.request({ url: req.url, //引入我的接口是特殊声明的,所以我就不检测http/https了 method: req.method, data: req.data, header: req.header }) .then(res => { // 大多数请求中 success并不代表成功,需要我们自己检测statusCode来确保 if (res.statusCode === 200) { resolve(res.data) // 成功 } else { // 如果失败 检测是否直接提示信息 if(req.failToast) Taro.showToast({ title: '网络不好,请求失败!' }) reject(res) // 失败 } }) .catch(err => { // 如果失败 检测是否直接提示信息 if (req.failToast) Taro.showToast({ title: '网络不好,请求失败!' }) reject(err) }) .finally(() => { // 请求结束 关闭loading层 if (req.loading) Taro.hideLoading() }) })}复制代码
ok,请求方法写到这里我们暂时只能告一段落了
6.完善api.ts,声明全局域名以及每个接口的定义.
//定义全局请求地址,因为我们用到的地址是https://cnodejs.org/api/v1export const DOMAIN: string = 'https://cnodejs.org/'// 声明获取主题首页接口地址并导出export const topics: string = DOMAIN + 'api/v1/topics'复制代码
7.观察api,声明请求data文件,以及使用请求并返回promise以及返回类型 返回类型:cnodejs.org/api/v1/topi…自己观察我就不截图了。
// 请求主题接口参数类型export interface TOPICSDATA { page: number, tab: 'ask' | 'share' | 'job' | 'good', limit: number, mdrender?: boolean}// 获取主题的接口export interface TOPICS { id: string, author_id: string, tab: string, content: string, title: string, last_reply_at: string, good: boolean, top: boolean, reply_count: number, visit_count: number, create_at: string, author: TOPICSAUTHOR}// 作者的类型export interface TOPICSAUTHOR { loginname: string, avatar_url: string}复制代码
8.自定义获取方法,结合自己的请求方法返回新的promise对象
// 调用封装方法 返回promise对象 得到获取到的数据const getTopics = (data: Inter.TOPICSDATA): Promise<Inter.TOPICS> => { return doRequestAction({ url: Api.topics, data: data })}复制代码
9. 页面内可以调用getTopics方法拿到我们的数据
import { getTopics } from '../../utils/request/request'import { TOPICSDATA } from '../../utils/request/inter'useEffect(()=>{ let data: TOPICSDATA= { page: 1, tab: 'ask', limit: 10 } getTopics(data).then(res=>console.log(res)) },[])复制代码
至此,一个简易的封装就完美的结束了,但是在实际开发中为了自己的便利,我们会封装很多经常使用到的参数,这里只是提供一个封装思维,具体还需要在大家的项目中去思考怎么才能去优化代码。
10.总结
知识点
- es6语法: ...展开运算, 解构赋值, promise
- ts:类型声明, 可选项, type , any类型 ,单个类型定义
- 封装思维,文件拆分
版权声明:每个人都要有封装思维:Taro Es6承诺构建微信小程序的简单全局请求方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。