在项目中会遇到这样的情况,由于后台需要执行、计算一段时间(如计算积分、自动排课等)。这时前台请求一段时间后,得不到返回结果就会发生请求超时。
拿自动排课来说,如果一个学校上百个班级,执行一次排课可能需要1-2分钟甚至更长时间,那么会造成前台访问接口超时(当然也可以延长超时时间实现)。
解决方案:
考虑改造为轮询查询程序执行结果。
后台改造:
将自动排课功能的接口分为两个:
创建线程执行自动排课
提供接口查询排课结果
对原有的方法进行改造:原有的方法,方法执行完成后才会返回执行结果。时间过长,考虑将原方法改造为线程执行,这样一旦线程开始执行,就可以返回结果。
改造方法:
自动排课功能所在的service类实现Runnable接口,将自动排课的实现逻辑写在run方法中。
编写方法创建并执行线程,执行run方法。
Controller层调用方法实现自动排课功能。
对于自动排课结果,可以放在redis中,接口实时更新自动排课的状态(成功或者失败),可以通过接口每间隔一段时间查询自动排课的结果。
代码示例:
//自动注入排课功能所在的service
@RequestMapping(value='/arrange/{id}')
}
//查询自动排课结果,并返回
}
}
//自动paike
this.scheduleId=scheduleId;//设置run方法中需要用的参数
taskExecutor.execute(this);//执行线程
returnResponseMessagok();//返回线程执行结果
}
//自动排课,线程
//排课逻辑代码
StringscheId=this.scheduleId;//使用接收的参数
}
}
前端大致分两次请求后台接口:
第一次请求接口自动排课(线程或者mQ执行),这样在启动自动排课的时候就返回请求结果,告知用户正在进行排课。
然后轮询调用第二接口,每隔几秒钟就去查询排课的结果。如果返回的状态为0代表排课成功,提示用户;如果返回的状态为1达标排课失败,提示失败原因;如果返回的状态为2代表排课正在执行中,继续轮询访问查询排课结果的接口。
主要代码示例:
varintervalFlag=true;//是否执行轮询的标志
//_post2是封装的ajax请求,
$._post2('/arrange/'+_id,{},function(res){
//调用接口,查询自动排课结果,加上这个是为了用户点击后立马访问,ajax同步访问,
//因为这次的查询结果决定了,是否执行轮询。
//第一次查询结果表明排课还在进行中,才会执行轮询。
//如果第一次已经返回结果表示程序执行完成,就不需要轮询访问排课结果了。
interval(_i;
}
});
//进度查询
$._post2('/arrangeResult/'+_id,{},function(res){
if(res.arrangeStatus==0){
//排课成功
clearInterval(interVa;//清空轮询
intervalFlag=false;//设置为不执行轮询
}elseif(res.arrangeStatus=={
//排课失败
}elseif(res.arrangeStatus=={
//排课进行中,什么都不做
}
});
}
//隔两秒访问
//定时器
//获取返回对象
},2000);
}
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点