【小程序-慕尚花坊05】项目中网络请求封装_慕尚花坊图片服务器过期
项目中网络请求封装
- 一,项目中网络请求封装
如需转载,请附上链接https://blog.csdn.net/m0_59269218/article/details/151030396
一,项目中网络请求封装
本篇文章依旧是慕尚花坊网络封装篇,从前面三篇网络请求是自定义底层逻辑的封装,为了和项目统一,这里使用项目自定义的 mina-request 实现功能,其请求地址如下: https://www.npmjs.com/package/mina-request
在学习本系列之前,再次先提供一下尚硅谷给的接口文档和笔记资料,以及自己代码的仓库地址
接口文档:https://s.apifox.cn/6ed6c5c4-56c4-4619-8e2a-4817aa140e30
笔记资料:https://www.yuque.com/bigweb/dpa5f7/dm2ygniwxksuxy6o
学习视频对应链接:https://www.bilibili.com/video/BV1LF4m1E7kB
本系列个人的gitee仓库地址:https://gitee.com/zhenghuisheng/mu-shanghua-fang
1,npm安装request请求
接下来就是继续安装 mina-request 请求模块,可以通过上面那个官方文档跟着安装就行,安装完成之后,就会出现成功增加一个包的提示
npm install mina-request
随后点击工具,在点击构建npm,随后出现完成构建npm的标志。在miniprogram_npm文件夹中,就会出现mina-request 这个新文件夹,里面就是刚刚安装的一些东西
随后将request.js文件中的WxRequest引入方式修改一下,将./request改成刚刚安装的mina-request,这样就能保证后面的逻辑能和项目的一致,因为前面三篇自己封装的,难免可能会和老师封装的不太一致
// import WxRequest from \'./request\'import WxRequest from \'mina-request\'
需要在响应拦截器中对返回的数据进行打印,点击测试请求按钮之后,可以发现相应的数据已经返回
instance.interceptors.response = async (response) => { console.log(response)}
2,http.js文件
前面三篇文章已经将http.js文件写了一遍,这里由于是正式项目的网络请求封装,因此再这里再写一遍,这里稍微回会和前面写的http.js文件有点不一样,需要经过小部分的改动,这里只对里面的代码进行拆分与讲解,合起来就是完整代码,整个文件的详细代码可以访问git地址:https://gitee.com/zhenghuisheng/mu-shanghua-fang
2.1,定义默认请求文件
首先第一步就是定义一个默认的实例,再定义前,需要将之前引入的 ./request
替换成mina-request
,然后构建一个默认的 WxRequest
实例,定义url前缀、超时时间以及是否需要isLoading加载,这里默认为true
// import WxRequest from \'./request\'import WxRequest from \'mina-request\'import { clearStorage, getStorage } from \'./storage\'import { modal, toast } from \'./commonApi\'// 对 WxRequest 进行实例化,不管是这里还是外面都是用上面定义的构造方法// 只要是对象即可,不会像java一样那么严格const instance = new WxRequest({ baseURL: \'https://gmall-prod.atguigu.cn/mall-api\', timeout: 15000, isLoading: true})
2.2,定义请求拦截器
在调用服务器接口的时候,需要判断一下是否携带token,所以就需要定义一个请求拦截器判断token是否携带,需要从storage本地缓存中获取,存的话一般是在登录后服务器把token返回给前端存储,再请求拦截器中只需要取token就好,将取到的token存到header请求头中
// 定义默认的请求拦截器instance.interceptors.request = (config) => { // 从本地获取 token const token = getStorage(\'token\') if (token) { // 如果存在 token ,则添加请求头 config.header[\'token\'] = token } return config}
2.3,定义相应拦截器
定义相应拦截器稍微回比请求拦截器复杂一些,需要通过服务器返回的数据进行对应的业务逻辑判断:
- 首先是对
isSuccess
这个布尔类型的数据进行判断,只要请求能访问到服务器,isSuccess就会返回true,如果返回的isSuccess是false,那么就说明请求没到服务器,网络出现异常 - 其次是对服务器返回的code进行业务逻辑判断,如果code返回的是200,那么表示请求返回成功
- 如果code返回的是208,那么表示此次请求用户没传token或者token已经失效,并且清除缓存跳转到登录页
- 如果code既不是200也不是208,那么抛出一个默认异常
注意:这里的code均为该项目后端自定义的code,不要和其他项目混合
// 定义默认的响应拦截器instance.interceptors.response = async (response) => { console.log(response) const { isSuccess, data } = response // 出现网络异常,正常来说只要请求能访问到服务器,isSuccess就会返回true // 不管后端的code是多少,如果返回的isSuccess是false,那么就说明请求没到服务器,网络出现异常 if (!isSuccess) { toast({ title: \'网络错误\', icon: \'error\' }); // 抛出异常 return Promise.reject(response); } // 如果isSuccess返回true,那么就需要对后端返回的code进行判断及做相应的业务 switch (data.code) { // code 等于 200,后端返回的是请求成功的数据 case 200: return data // 如果是208,那么说明没有token或者token失效 case 208: const res = await modal({ content: \'鉴权失败,请重新登录\', showCancel: false }) if (res) { // 清除用户信息,如token clearStorage() // 跳转到登陆页面 wx.navigateTo({ url: \'/pages/login/login\' }) } return Promise.reject(response) // 其他code做统一的异常封装 default: toast({ title: \'程序异常,请联系客服或稍后重试!\' }) // 抛出异常 return Promise.reject(response) }}
完成前面三个操作之后,最后将实例暴露出去,那么外部就能调用
// 将 WxRequest 的实例通过模块化的方式暴露出去export default instance
2.4,请求调用测试
在test.wxml文件中,定义一个按钮,并且绑定一个事件handler
<view><button bindtap=\"handler\">测试请求</button></view>
在test.js文件中,定义这个handler自定义事件,并且发起请求,请求后将异常捕获,如测试这个正确的请求
import instance from \'../../utils/http\'Page({ // 点击按钮触发 handler 方法 async handler() { // 请求并且进行异常捕获 const res = await instance.get(instance.get(\"/index/findBanner\").catch((error) => { console.log(error) return error })) console.log(res) }})
点击按钮之后,其效果如下,会返回相应的数据,isSuccess为true,code为200。
3,设置环境变量
在实际开发中,不同的开发环境,调用的接口地址是不一样的。例如开发环境需要调用开发版的接口地址,生产环境需要调用正式版的接口地址,这时候,我们就可以使用小程序提供了 wx.getAccountInfoSync()
接口,用来获取当前账号信息,在账号信息中包含着 小程序 当前环境版本。
微信小程序客户端的官网地址如下:https://developers.weixin.qq.com/miniprogram/dev/api/
接下来在app.js文件中对这个接口进行测试,看一下可以获取到哪些信息
App({ onShow(){ const countInfo = wx.getAccountInfoSync() console.log(countInfo) }})
其效果如下,打印了appId以及envVersion,envVersion 就是这里需要的环境变量
接下来在utils文件下新建一个env.js文件,在小程序开发中一般会有三个环境:开发版,体验版,正式版
- 开发版一般指的是开发人员正在开发的版本,并且没在小程序后台管理变成体验版
- 体验版需要管理人员将开发版手动设置成体验版,有体验权限的人才能看到
- 正式版需要管理人员将体验版手动设置成正式版,需要通过腾讯那边审核,审核通过就能被用户访问
一般不同环境访问服务器的域名端口等都不太一样,比如需要连接后端的本地环境或者测试环境等,因此需要通过不同的环境设置不同的域名,获取域名就可以直接导入引用这个js文件即可
// 获取 小程序帐号信息const { miniProgram } = wx.getAccountInfoSync()// 获取小程序当前开发环境// develop 开发版, trial 体验版, release 正式版const { envVersion } = miniProgramlet env = { baseURL: \'https://gmall-prod.atguigu.cn/mall-api\'}switch (envVersion) { case \'develop\': env.baseURL = \'https://gmall-prod.atguigu.cn/mall-api\' break case \'trial\': env.baseURL = \'https://gmall-prod.atguigu.cn/mall-api\' break case \'release\': env.baseURL = \'https://gmall-prod.atguigu.cn/mall-api\' break default: env.baseURL = \'https://gmall-prod.atguigu.cn/mall-api\' break}export { env }
4,调用接口方式说明
为了更好统一管理所有的api请求,那么就需要在 miniprogram 目录下新建一个api文件夹,后续所有的请求都会放到这个api文件目录下,比如index页面,那么就在api文件夹下面新建一个index.js文件,index.js文件内容如下
// 导入http模块import http from \'../utils/http\'// 定义请求,比如一些关于index页面的增删改查都在这个文件下面定义export const findBanner = () => http.get(\'/index/findBanner\')
再回到index页面的目录下,其index.js文件内容如下,需要引入api文件夹下的index.js文件,并且引入刚刚定义的获取banner的请求,然后在onLoad生命周期调用这个findBanner方法即可
// 导入接口 APIimport { findBanner } from \'../../api/index\'Page({ // 小程序页面加载时执行 onLoad () { // 调用获取首页数据的方法 this.getHomeList() // 使用 this 来调用页面内的方法 }, // 获取首页数据 async getHomeList() { try { // 获取轮播图数据 const res = await findBanner() console.log(\'轮播图数据为\' + JSON.stringify(res)) } catch (error) { console.error(\'获取首页数据失败:\', error) // 错误处理 } }})
在普通编译之后,其打印的数据如下,可以发现这个轮播图数据成功打印出来
到此为止,整个网络请求相关的封装到此结束,后续调用后端的接口直接通过上面这种方式即可,在api文件中定义相关请求,在页面中的业务.js文件中引入api请求即可,让页面中的js文件更加的关注自己的业务实现即可,同时通过层层封装的方式实现高内聚、低耦合