问题描述:当后台进行一个比较费时的任务,比如前台创建爬虫任务,当创建完成后,后台进行数据爬取,爬取过程需要耗费一些时间。为了及时获知爬虫任务完成,前端需要定时向后端发送查询爬虫任务状态(爬取中或已完成)的请求,如果爬取状态为“爬取中”,则继续向后台发送查询状态请求;如果爬取状态为“已完成”,则结束该请示请求任务。
解决方法:
(1)使用原型链存储定时器相关数据:防止爬虫页面跳转到其他页面,再跳转爬虫页面时,数据被初始化的问题。
在【main.js】定义变量timerArr,挂载在原型链上。
// 创建全局定时器数组
Vue.prototype.$timerArr = [];
(2)使用定时器向后台请求:当前台创建爬虫任务后,获取后端返回的爬虫任务id,该id用于区分不同爬虫任务,为不同爬虫任务创建定时器,定时向后端发送查询爬虫任务状态请求,当爬虫完成时,需要找到当前完成的请求,将其定时器清除
// 提交创建采集任务
submitCreatTask() {
this.creatTaskDialogVisible = false;
const loading = this.$loading({
lock: true,
text: "正在新建采集任务,请稍等",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.6)",
});
//***** 创建采集任务*****
CrawlTaskCreat(this.taskForm)
.then((res) => {
if (res.data.status == 200) {
this.$message.success("新建采集任务成功");
this.statusValue = "RUNNING";
this.page_index = 1;
this.getTaskList();
let taskId = res.data.data.taskId;
console.log("开始启动定时器");
let timer = setInterval(() => {
this.func(taskId);
}, 5000); //每5秒向后台发送一次请求
// 将数据存储到原型链
this.$timerArr.push({ taskId: taskId, timer: timer });
}
loading.close();
})
.catch((err) => {});
},
// 新创建了一个采集任务,则为其添加一个查询爬取状态的定时器
func(id) {
setTimeout(() => {
if (!!id) {
let param = { data: [{ taskId: id }] };
taskStatusGet(param).then((res) => {
if (res.data.status == 200) {
if (res.data.state == "已完成") {
console.log("完成",JSON.stringify(this.$timerArr));
const h = this.$createElement;
this.$notify({
title: "采集任务完成!",
duration: 5000, //显示时间
message: h(
"i",
{ style: "color: teal" },
`${res.data.data[0].taskName} 采集完成`
),
type: "success",
});
// 根据taskId判断哪个任务已完成
let index = this.$timerArr.findIndex(
(item) => item.taskId == id
);
console.log(`当前完成${index},id为${id}`);
clearInterval(this.$timerArr[index].timer);
this.$timerArr.splice(index, 1);
//重新查询采集中的数据
this.statusValue = "RUNNING";
this.page_index = 1;
this.getTaskList();
}
}
});
}
}, 0);
},