一. 使用场景
使用环境: vue3
当需要处理多个异步任务时,想要控制并行异步任务的数量,不想所有任务同时执行导致产生性能上的问题,
比如当需要同时发起多个网络请求,但又不想一次性发出过多请求导致服务器压力过大或者浏览器资源耗尽时,这个钩子就可以派上用场
二. 效果
测试代码:
const taskControl = useParallelTaskControl(3)
const testTaskControl = () => {
for (let i = 0; i < 100; i++) {
taskControl.addTask(async () => {
await new Promise((resolve) => {
setTimeout(() => {
console.log('执行任务:', i,'剩余任务:', taskControl.remainingTasks.value,'正在执行数量:',taskControl.activeTasks.value )
resolve('')
}, i % 2 ? 2000 : 3000)
})
})
}
}
onMounted(() => {
testTaskControl()
})
三. 代码
import {ref, computed, watch} from 'vue';
/**
* 并行任务控制的自定义钩子
* @param maxParallel 最大并行任务数量
*/
export function useParallelTaskControl(maxParallel=8) {
// 存储待执行的任务数组
const tasks = ref<Function[]>([]);
// 当前正在执行的任务数量
const activeTasks = ref(0);
// 当前要执行的任务的索引
const taskIndex = ref(0);
// 执行单个任务的
const runTask = async () => {
if (taskIndex.value < tasks.value.length) {
activeTasks.value++;
taskIndex.value++;
const currentTask = tasks.value[taskIndex.value-1];
try {
await currentTask();
} catch (error) {
console.error('Task error:', error);
} finally {
activeTasks.value--;
// 任务完成后,检查是否还有任务需要执行
await runTask();
}
}
};
// 监听任务数组和正在执行任务数量的变化
watch(() => [activeTasks,tasks],async () =>{
if (activeTasks.value < maxParallel && taskIndex.value < tasks.value.length-1) {
await runTask();
}
},{
deep: true
})
// 添加任务的函数
const addTask = (task: Function) => {
tasks.value.push(task);
};
// 清空任务的函数
const clearTasks = () => {
tasks.value = [];
taskIndex.value = 0;
activeTasks.value = 0;
};
return {
// 添加任务
addTask,
// 清空任务
clearTasks,
// 正在执行的任务数量
activeTasks,
// 剩余任务数量
remainingTasks: computed(() => tasks.value.length - taskIndex.value)
};
}
四. 参数及返回说明
- 参数
最大并行数量: maxParallel [number]
- 返回
添加任务:addTask
需要传一个函数,这个函数会添加到任务队列中
清空任务: clearTasks
正在进行的任务数量:activeTasks
剩余任务数量: remainingTasks