微信小程序中网络请求缓存的解决方法
微信(小程序)  /  管理员 发布于 4年前   584
需求 提交小程序审核时,有一个体验测评,产品让我们根据小程序的体验测评报告去优化小程序。 其中有一项是网络请求的优化,给我们出了很大的难题。 文档中是这样解释的:3分钟以内同一个url请求不出现两次回包大于128KB且一模一样的内容 看到这个问题的时候,首先想到的是在响应头上加上cache-control,经过测试发现小程序并不支持网路请求缓存。搜索发现官方明确答复,小程序不支持网络请求缓存:wx.request不支持http缓存 既然官方不支持网络请求缓存,那只能自己想办法解决这个问题了。 先来看一下需求:3分钟内,同一请求只能请求一次。 分析 分析: 前两点比较好实现,虽然小程序不支持网络请求缓存,但我们还是可以利用cache-control来实现这个功能。 首先网络请求需不需要情缓存统一交给服务端去做,服务端在处理GET请求时,统一加上响应头cache-control,如果需要缓存就用max-age=180,如果不需要做网络请求就用no-cache。前端根据响应头信息自己做前端缓存。 其中的难点是前端如何知道服务端数据有没更新,如果服务端数据更新了,前端还是使用缓存这是有问题的。 经过一番思考后发现,前端提交数据后,相应的GET请求数据会更新,也就是说前端只要有数据提交,就应该把缓存清空。 这有一个难点,当前端提交数据时,前端是不知道哪些GET请求会因此更新数据,所以这个问题我们没有解决,我的方法比较粗暴:只要前端提交了数据,就将所有缓存清空。这是一个治标不治本的问题。 实现 公司项目封装了HTTP请求 拦截请求,如果是GET请求,检查缓存, 缓存网络请求 两个工具函数 设置网络请求 处理网络缓存 响应头全部变成小写,在小程序中,无法确定响应头的大小写会导致报错,所以统一处理响应头 总结 有一点没有说,就是这个缓存是保存在哪里的? 既没有用localStorage,也没有用globalapp,用的是类的静态属性。 这样做有3个好处: 我在使用时遇到一个坑,是因为自己没有理解:类能保存数据的,不能保存状态,但类的对象是既可以保存数据,也可以保存状态的。 最后,此方法还是有很大的优化空间。 好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家的支持。if (request.method.toLowerCase() === "get"){ // param 请求信息 const cache = this.handleCatchControl(request) if (!cache.isRequest) return this.listener.onApiResponse(request, 200, cache.data), sequence; //将缓存返回给对应的请求}
// param 响应头,上下文,响应数据this.setCatchControl(headers, context, response.data)
//如果同时发起多个`GET`请求,需要拼接之前缓存数据ApiAgent.cacheData = Object.assign(ApiAgent.cacheData,{ [context.request.url]: { //api data, //响应数据 expireTime: Number(cacheControl.split("=")[1] + '000'), //过期时间 cacheTime: new Date().getTime(), //缓存时间 }})
// param 响应头,上下文,响应数据setCatchControl(responseHeader: any, context: any, data: any) { if (context.request.method.toLowerCase() === "get") { const headers = HandleHeaders.get(responseHeader) const cacheControl = headers["cache-control"] if (cacheControl && cacheControl !== "no-cache") { ApiAgent.cacheData = Object.assign(ApiAgent.cacheData,{ [context.request.url]: { data, expireTime: Number(cacheControl.split("=")[1] + '000'), cacheTime: new Date().getTime(), } }) } } else { ApiAgent.cacheData = {} }}
// param 请求信息handleCatchControl(request): any { const cacheArr = ApiAgent.cacheData if (Object.keys(cacheArr).length === 0) return { isRequest: true } let cache = {} Object.keys(cacheArr).forEach(cacheArrKey => { if (cacheArrKey === request.url) { cache = cacheArr[cacheArrKey] } }) const newDate = new Date().getTime() if (newDate - cache.cacheTime < expireTime){ return { isRequest: false, data: cache.data } } return { isRequest: true}}
class HandleHeaders { static get(headers: { [key: string]: string }) { const headersData: any = {} Object.keys(headers).forEach(key => { headersData[key.toLowerCase()] = headers[key] }) return headersData }}
您可能感兴趣的文章:
123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..路人 在
php中使用hyperf框架调用讯飞星火大模型实现国内版chatgpt功能示例中评论 教程很详细,如果加个前端chatgpt对话页面就完美了..Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号