在查询大量数据或使用第三方查询数据时,数据量较大、查询效率较低,往往在前端点击查询按钮后需要等待很久,也无法获取到查询进度,所以,我们可以根据redis缓存来实现实时进度查询+显示上次查询时间的功能+同一时间只允许一人查询功能。
页面
在不查询的时候,页面时这样子的
点击查询后,出现查询进度并实时更新,按钮置为灰色
查询完毕后,更新时间
后端
实现功能
实时缓存查询进度
查询完毕显示上次查询时间
同一时间只允许一人查询
public void select() {
String checkStatus = jedisclient.get(myKey);
//如果发现在进度中,说明有人正在查询,直接返回
if (checkStatus != null && checkStatus.contains("Progress")){
return;
}
//获取需要查询的数据
List<String> userIds = userMapper.selectAll();
//如果需要更新的数据量为零,直接写入时间戳,作为上次查询时间
if (userIds == null || userIds.size() == 0){
jedisclient.set(myKey, Integer.toString(system.currentTimeMillis()));
return;
}
//异步查询
ThreadPoolUtil.doExecutor(()->{
int total = userIds.size();
int pageNum = 0;
//分页查询
while (pageNum <= total){
List<String> ids = userIds.subList(pageNum, Math.min(pageNum+20, total));
ids.forEach(id -> {
//第三方查询操作 或 查询数据库
});
//实时更新查询进度
jedisclient.set(myKey, "Progress:" + Math.round(pageNum * 100 / total) + "%");
pageNum += 20;
}
//查询完毕,设置时间戳,作为上次查询时间
jedisclient.set(DISPUTE_REFRESH_CHECK_STATUS, Integer.toString(YamiDateUtil.get_LA_Second()));
});
}
//提供一个接口来实现获取redis缓存
public String getCheckStatus(){
return jedisclient.get(DISPUTE_REFRESH_CHECK_STATUS);
}
前端
实现功能
内容实时刷新到在页面
在查询时,显示进度
在不查询时,显示按钮和上次查询时间
我用的是AngularJS,代码写了个大概,主要提供思路
//首先实现一个初始化任务,页面打开就执行,用来初始化页面上要显示的上次更新时间
$scope.$watch('$viewContentLoaded', function() {
//写一个定时器,每2秒执行一次getCheckStatus方法
//在初始化页面的时候,就开始循环查询redis缓存
interval = setInterval(getCheckStatus, 1000);
});
//再写一个方法,用户点击之后执行
vm.select= function () {
//发送http请求,调用后端方法,进行查询
disputeService.select();
//点击这个方法的时候也要执行定时器,每两秒调用一次方法,用来实时更新进度
interval = setInterval(getCheckStatus, 1000);
};
//查询redis缓存的方法
function getCheckStatus() {
//发送http请求,调用后端方法,获取redis缓存
disputeService.getCheckStatus().success(function (data){
if (data.body.charAt(0)==='P') {
//如果redis缓存是进度,设置i为0,不结束定时器
checkProgress = data.body;
isUsed = true;
i = 0;
} else {
//如果redis缓存是时间,将时间格式化,并表现在页面
checkTime = moment(data.body * 1000).format("MM-DD HH:mm");
isUsed = false;
i++;
//五次查询缓存都是时间,就关闭定时器
if (i === 5){
clearInterval(interval);
}
}
});
}