说明
- 前端会遇到这种需求,希望多个请求并发加快前端反应速度,但又要限制同时请求的数量,防止服务器压力过大
- 以下代码由Trae里的千问模型生成,思路真牛
方案
async function batchQuset(){
this.$store.commit('openLoading')
const questNum = this.paramsList.length
// 每批最多 3 个并发请求
const BATCH_SIZE = 3
// 保持顺序的结果数组
const numResList = new Array(questNum).fill(null)
// 并发控制函数
const runWithConcurrency = async (tasks, concurrency) => {
const results = []
// 维护一个正在执行的 Promise 列表(控制并发就靠它)
const executing = []
for (const task of tasks) {
// p 是 then() 方法返回的新 Promise,不是 task() 的原始 Promise
const p = task().then((result) => {
// 当task执行完成后,从executing数组中移除
executing.splice(executing.indexOf(p), 1)
return result
})
results.push(p)
executing.push(p)
// 当正在执行的任务数量超过并发限制时,等待任意一个完成
if (executing.length >= concurrency) {
// 等有完成的Promise时,外面的for循环才能继续走
await Promise.race(executing)
}
}
// 走到这里时,仅剩下小于并发数量的Promise还没彻底完成
return Promise.all(results)
}
// 创建所有校验任务[Promise,Promise]
const tasks = this.paramsList.map(
(params, index) => async () => {
const { pass, res } = await questApi(params)
this.$store.commit(
'openLoading',
`进度: ${index + 1}/${questNum}`
)
return { index, pass, res }
}
)
// 执行并发校验
const results = await runWithConcurrency(tasks, BATCH_SIZE)
// 按原始顺序填充结果
results.forEach(({ index, pass, res }) => {
if (!pass) {
numResList[index] = res
}
})
// 过滤掉 null 值,得到最终的列表
const resList = numResList.filter((item) => item !== null)
this.$store.commit('closeLoading')
// *****请求结果resList进行展示/处理******
}
说明
- this.$store.commit('openLoading')是自己把element的loading二次封装,方便唤起和改文字
import Vuex from "vuex";
import { Loading } from 'element-ui';
export default new Vuex.Store({
state: {
// 全屏loading实例
loading: null,
},
mutations:{
openLoading(state, str) {
if (state.loading) {
state.loading.setText(str)
} else {
state.loading = Loading.service({
lock: true,
text: str,
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
customClass: 'phone-loading'
})
}
},
closeLoading(state) {
state.loading?.close()
state.loading = null
},
}
})
- then 中 return result 的作用 :
- 当 then 的回调函数执行完毕后, p 这个 Promise 会被 resolve
- p 被 resolve 的值就是 return 后面的值
- 如果 return result ,则 p 解析为 result
- 如果不 return 或 return undefined ,则 p 解析为 undefined
// 示例 1:return result
const p1 = task().then((result) => {
console.log('收到 result:', result) // 假设 result = '任务完成'
return result // return '任务完成'
})
p1.then((value) => {
console.log('p1 的值:', value) // 输出:'任务完成'
})
// 示例 2:不 return
const p2 = task().then((result) => {
console.log('收到 result:', result) // 假设 result = '任务完成'
// 没有 return 语句
})
p2.then((value) => {
console.log('p2 的值:', value) // 输出:undefined
})
// 示例 3:return 其他值
const p3 = task().then((result) => {
console.log('收到 result:', result) // 假设 result = '任务完成'
return '修改后的值'
})
p3.then((value) => {
console.log('p3 的值:', value) // 输出:'修改后的值'
})