现在因为有个上传组件他用到了这个mixin文件,这个mixin文件中mounted请求了接口,这样一个页面中如果有多个上传组件的话,那么就会导致一上来就会一次性请求多个重复的接口,有什么好点的方法吗,如果不放在vuex中的话
现在因为有个上传组件他用到了这个mixin文件,这个mixin文件中mounted请求了接口,这样一个页面中如果有多个上传组件的话,那么就会导致一上来就会一次性请求多个重复的接口,有什么好点的方法吗,如果不放在vuex中的话
我遇到了类似的问题,我的场景是一个图片加载组件在mounted的时候会根据props的图片id去请求图片的url,在列表中展示时,会请求很多次。这个接口是支持单个图片id作为参数 同时也支持id数组作为参数的,也就是说我可以一次请求多个图片id,当调用该接口时,我将短时间内的请求参数进行收集然后合并为一个请求,拿到结果后再进行分发。公司代码不便展示 我这里写了个demo可以参考一下
let isCollecting = false
const range = 200
const stack = []
// 模拟http请求
const fetchData = (params) => {
return new Promise((resolve) => {
setTimeout(() => {
if (Array.isArray(params)) {
const list = params.map(item => {
return {
id: item.id,
url: 'url:' + item.id
}
})
resolve(list)
} else {
resolve(
{
id: params.id,
url: "url:" + params.id
}
)
}
}, 50)
})
}
// 收集请求
const mergeRequest = (params) => {
return new Promise((resolve) => {
if (!isCollecting) {
console.log('开始收集')
isCollecting = true
if (Array.isArray(params)) {
stack.push({
params, resolve
})
} else {
stack.push({
params, resolve
})
}
console.log('创建定时器 200ms后清空stack')
setTimeout(async () => {
await clearStack()
console.log('清空stack')
isCollecting = false
}, range)
} else {
console.log('收集')
stack.push({
params, resolve
})
}
})
}
// 合并请求参数,发起请求,处理结果
const clearStack = async () => {
const paramsList = stack.reduce((acc, cur) => {
if (Array.isArray(cur.params)) {
acc.push(...cur.params)
} else {
acc.push(cur.params)
}
return acc
}, [])
const res = await fetchData(paramsList)
stack.forEach(item => {
const { params, resolve } = item
const obj = {
}
if (Array.isArray(params)) {
obj.params = params
obj.result = params.map(v => {
return res.find(tar => tar.id === v.id)
})
resolve(obj)
} else {
obj.params = params
obj.result = res.find(tar => tar.id === params.id)
resolve(obj)
}
})
console.log('clearSatck')
stack.length = 0
}
// 延时函数
const sleep = async (num) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, num);
})
}
//
const fn = async () => {
mergeRequest({ id: 1 }).then(res => {
console.log(res)
})
await sleep(100)
mergeRequest([{ id: 2 }, { id: 3 }, { id: 4 }]).then(res => {
console.log(res)
})
await sleep(100)
mergeRequest({ id: 5 }).then(res => {
console.log(res)
})
await sleep(100)
mergeRequest({ id: 6 }).then(res => {
console.log(res)
})
}
fn()
你可以全局调用 getSignature()
一次把结果存起来,组件里直接拿结果
或给你的 getSignature()
加个缓存机制,如
let signature = null
const getSignature = () => signature ??= httpGet('...')
给请求加下缓存 思路如下:
定义一个数组 const a = []
然后每次请求给url push 到数组里 作为唯一值
请求完毕弹出对应的url
如果下次请求判断里面有这个url 那么就不再进行请求
那这样肯定不能把getSignature
放到mixin
了,因为你要保持只请求一次,不然处理起来有点复杂,就没太大必要了。
可以在App
的mounted
就调用一次。
如果你不想使用vuex
,那可以通过sessionStorage
来获取。
也可以通过把数据写到vue
的prototype
中,这样在用到的地方就可以通过this.$xxx
来获取。
简单粗暴版:
在初始化时请求接口并保存,然后 getSignature 中直接读取该数据即可,伪代码:
app.js
global.sign = await api();
app.start();
mixin.js
{getSign: () => global.sign}
正常版本:
let cache = null;
async getSignature = () => {
if(cache) return cache;
return await api();
}
10 回答11k 阅读
6 回答2.9k 阅读
5 回答4.7k 阅读✓ 已解决
4 回答3k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
这种情况下的 getSignature 最好是 Singleton 的,可以写个模块导出。mixin 里的 getSignatrue 都直接引用或调用这个 Singleton 的 getSignature。
因为大家都调同一个 Signature,那么可以在这里做一些判断和处理,基本思路就是,