vue+elementui后台管理系统的任务状态不会实时更新,需要用户手动刷新才能实现

今天,项目提测之后,测试同学提出了一个bug,就是一些新建任务从创建到完成需要一个时间段,任务详情页和列表页就会任务状态不会实时更新,需要用户手动刷新才能实现。

针对这个问题,我考虑通过轮询来实现。

实现轮询的两种方式:websoket和定时器
复制代码

通过和项目组的同学讨论,先使用定时器来实现,以后再优化成websoket方式。

一、项目涉及的六个状态:

pending(待调度) running(运行中) success(成功) failure(失败) revoked(被终止) offlineSkip(下线跳过)
复制代码

6种状态划分为2类:

完成状态:success、failure、revoked、offlineSkip
未完成状态:pending、running
复制代码

6种状态会出现2种结果:

pending->running->success/failure/revoked/offlineSkip

running->success/failure/revoked/offlineSkip
复制代码

判断任务是否处于完成状态:

// 判断任务是否已完成
export const finished = (status: string): boolean => {
    status = status.toLowerCase();
    return status === 'failure' || status === 'revoked' || status === 'success' || status === 'offlineskip';
};
复制代码

二、实现详情页的需求。

详情页的就比较简单了。首次调用详情接口时,查看返回的任务状态,如果返回的是完成状态,直接展示该状态就可以了。如果是未完成状态,就需要设置一个定时器来重复调用详情接口,直至返回完成状态,清楚定时器。

async getJobDetail (DaemonJobId, index) {
    const detail: any = await getJobDetail({
        _releaseId: this.releaseId,
        _jobId: DaemonJobId
    });
    const { Status } = detail.data;
    if (!finished(Status)) {
        this.timer = window.setTimeout(() => {
            this.getJobDetail(DaemonJobId, index);
        }, 5000);
    } else {
        clearTimeout(this.timer);
    }
}
复制代码

三、实现列表页面的需求。

列表页因为涉及翻页功能(page>1),所以不能通过简单的调用列表接口(page=1)来实现。如果一直刷新列表页面,该页面就无法实现翻页功能。

所以这块实现,我先去遍历了列表信息,未完成状态去调详情接口,直到返回完成状态,通过set直接页面视图。

// 循环列表数据
list.forEach(async (ele, index) => {
    if (!finished(ele.Status)) {
        this.getJobDetail(ele.DaemonJobId, index);
    }
});

// 调用详情接口
async getJobDetail (DaemonJobId, index) {
    const detail: any = await getJobDetail({
        _releaseId: this.releaseId,
        _jobId: DaemonJobId
    });
    const { Status, FinishedTime } = detail.data;
    if (finished(Status)) {
        this.$set(this.jobList[index], 'Status', Status);
        this.$set(this.jobList[index], 'FinishedTime', FinishedTime);
    }
    if (!finished(Status) && Status === 'Running') {
        this.$set(this.jobList[index], 'Status', Status);
        this.timer = window.setTimeout(() => {
            this.getJobDetail(DaemonJobId, index);
        }, 5000);
    }
    if (!finished(Status) && Status === 'Pending') {
        this.timer = window.setTimeout(() => {
            this.getJobDetail(DaemonJobId, index);
        }, 1000 * 60);
    }
}
复制代码

如果同时创建多个任务,每次运行中的任务之用一个,别的都是待调度状态。考虑性能,待调度状态就每隔1min调用一次详情接口就可以了,直到它变为运行中再每隔5s调用一次详情接口。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享