vue3+antd+ts,轮询展示进度条
·
功能介绍:
使用antd的progress进度条组件,将接口获取到的数据实时一条一条的生成若干个进度条。
每个进度条的上面展示进度条的名称,进度条的后面展示是否需要重新验证的按钮。
接口返回的是一个数组,里面有若干个对象,对象有name名称,id(唯一),status状态。
status一开始一般为null,说明这一条后台还在查询中未出结果,
如果status为0说明这一条正常,那么展示时,progress为100%;status若为1,说明这一条异常,对应的progress为50%,进度条的后面要展示“重新验证”按钮。
点击“重新验证”按钮时,此进度条的名字不隐藏,但进度条和按钮要隐藏。点击按钮调用传递对应的唯一值进行上面接口的轮询,直到这一条name的status不为null,此时隐藏的进度条可以再次展示。
循环直到所有的结果status都不为null。在这个过程中,如果某一条的结果不为null,页面就开始展示,等待下一个status不为null的返回,有则在后面展示,展示的顺序是status不为null的返回顺序。
如果接口结果一下子全返回了status不为null的,可以按照接口获取到的顺序,但要保持页面的进度条间隔一秒一条的展示,直到接口所有的数据不为null在页面展示完。
核心代码:
// 存储所有进度条数据
const allProgressData = ref([])
// 存储已展示的进度条数据
const displayedProgressData = ref([])
// 轮询定时器
const pollInterval = ref(null)
// 展示定时器
const displayInterval = ref(null)
// 是否正在加载
const isLoading = ref(true)
// 发送验证
const sendVerify= async (id) => {
const mockData = await sendVerify(id)
if (!id) {
startPolling()
}
};
// 查询结果
const getProRes = async () => {
const mockData = await queryRes()
return mockData;
};
// 开始轮询获取进度数据
const startPolling = () => {
// 清除现有定时器
if (pollInterval.value) {
clearInterval(pollInterval.value)
}
if (displayInterval.value) {
clearInterval(displayInterval.value)
}
try {
// 设置新的轮询定时器(每3秒轮询一次)
pollInterval.value = setInterval(async () => {
try {
const data = await getProRes();
allProgressData.value = data;
// 检查是否所有项目都有结果
const allHaveResults = data.every(item => item.status !== null)
if (allHaveResults) {
clearInterval(pollInterval.value)
pollInterval.value = null
isLoading.value = false
}
} catch (error) {
console.error('获取进度数据失败:', error)
}
}, 3000)
// 初始调用一次
getProRes().then(data => {
allProgressData.value = data
})
// 设置定时器,每隔1秒检查并添加一个新的进度条
displayInterval.value = setInterval(() => {
// 查找第一个还没有显示且有结果的项目
const itemToAdd = allProgressData.value.find(item =>
item.status !== null &&
!displayedProgressData.value.some(displayed => displayed.id === item.id)
)
const reItem = displayedProgressData.value.filter(t => t.loading === true)
if (itemToAdd) {
displayedProgressData.value.push({
...itemToAdd,
loading: false,
percent: itemToAdd.status === 0 ? 100 : 50,
retryVerify: itemToAdd.status === 1
})
}
if (reItem.length) {
const updateMap = new Map(allProgressData.value.map((item) => [item.id, item]))
displayedProgressData.value = displayedProgressData.value.map((item) => {
const updateItem = updateMap.get(item.id)
if (updateItem) {
return {
...item,
status: updateItem.status,
loading: updateItem.status === null ? true : false,
percent: updateItem.status === 0 ? 100 : 50,
retryVerify: itemToAdd.status === 1
}
}
})
}
// 检查是否所有项目都已显示
const allDisplayedI = allProgressData.value.every(item => item.status === null)
const allDispalyedD = displayedProgressData.value.every(item => item.status === null)
if (allDisplayedI && allDispalyedD && allProgressData.value.length === displayedProgressData.value.length && displayInterval.value) {
clearInterval(displayInterval.value)
displayInterval.value = null
}
}, 1000)
} catch(err) {
console.log('err', err)
stopVerify()
}
}
// 处理重新验证
const handleRevalidate = (id) => {
try {
await sendVerify(id)
// 更新数据
const displayedIndex = allProgressData.value.findIndex(item => item.id === id)
if (displayedIndex !== -1) {
allProgressData.value[displayedIndex] = {
...allProgressData.value[displayedIndex],
status: null,
loading: true
}
}
startPolling()
} catch (error) {
console.error('重新验证失败:', error)
stopVerify()
}
}
const stopVerify = () => {
if (pollInterval.value) {
clearInterval(pollInterval.value)
}
if (displayInterval.value) {
clearInterval(displayInterval.value)
}
}
// 初始化
onMounted(() => {
sendVerify('')
});
// 清理定时器
onUnmounted(() => {
stopVerify()
})
// 计算已完成的项目数量
const completedCount = computed(() => {
return allProgressData.value.filter(item => item.status !== null).length
})
// 计算总项目数量
const totalCount = computed(() => {
return allProgressData.value.length
})
更多推荐



所有评论(0)