目前项目大都通过组件化来简化单页的复杂性,后期也很容易维护;
组件封装方面,我们要求:
- 样式独立
- 结构独立
- 有业务功能(网络请求等)必须在组件内完成;
这样一个复杂页面会引用很多组件,如果这些组件都有获取初始数据(或配置数据)的行为,这样在页面初始化时会产生大量相同网络请求,如下图:
虽然无伤大雅,程序也能正常进行,但是还是想把这样重复的请求统一合并下;优化后如下:
怎么优化处理呢?找了 网络请求管理器、请求合并 等相关的,但是没有合适的,这里需要防止并发重复请求;所以自己动手改造请求;
封装请求管理器类,通过类内部变量存储所有的请求记录(tasks)
check 用于检查5秒内是否有相同的请求
get 等同于 promise 封装的 wx.request,这里将去获取 set 的值
set 请求成功或失败时 set 下,tasks 里就存放了相应的结果
class rpcm {
tasks = {}
check(key) {
let nt = new Date().getTime()
if (this.tasks[key]) {
//console.log('resSetIntervalnt',nt , this.tasks[key].timeout)
if (nt <= this.tasks[key].timeout) {
return true
}
}
return false
}
get(key) {
return new Promise((success, fail) => {
let resSetInterval=setInterval(()=>{
console.log('resSetInterval',key,this.tasks[key])
if(this.tasks[key].type=='success'){
wx.hideLoading();
success(this.tasks[key].res)
clearInterval(resSetInterval)
}
if(this.tasks[key].type=='fail'){
wx.hideLoading();
fail(this.tasks[key].res)
clearInterval(resSetInterval)
}
},500)
})
}
set(key,type='',res=null) {
let nt = new Date().getTime()
this.tasks[key] = {
timeout: nt + 5000
}
if(type){
this.tasks[key]['type']=type
this.tasks[key]['res']=JSON.parse(JSON.stringify(res))
}
}
}
请求的处理,这里 myRequest 只是示例,请根据你的业务改造
function myRequest(url,params){
const RMT = new rpcm()
//cache_key 是url地址+请求参数params
// 如果已经存在可用请求,就直接去get 请求的结果
if (RMT.check(cache_key)) return RMT.get(cache_key)
RMT.set(cache_key)// 请求管理器中创建一个请求占用
return new Promise((success, fail) => {
wx.request({
url: url,
method: 'POST',
data: params,
success: function (res) {
success(res.data);
//将返回结果存入请求管理器
RMT.set(cache_key,'success',res.data)
},
fail: function (res) {
fail(res);
//将返回结果存入请求管理器
RMT.set(cache_key,'fail',res)
},
complete: function () {
wx.hideLoading();
}
})
})
}
这样在5秒内多次调用 myRequest , 相同的url和参数就只会发起一次请求,其它请求会去等待首次请求的返回结果;
为什么多次请求不能直接忽略掉呢?每个请求之后都有自己的业务要做,不能简单的忽略!