调用接口处理时间过长,前端访问超时解决方案

    在项目中会遇到这样的状况,因为后台须要执行、计算一段时间(如计算积分、自动排课等)。这时前台请求一段时间后,得不到返回结果就会发生请求超时。javascript

    拿自动排课来讲,若是一个学校上百个班级,执行一次排课可能须要1-2分钟甚至更长时间,那么会形成前台访问接口超时(固然也能够延长超时时间实现)。前端

解决方案:java

    考虑改造为轮询查询程序执行结果。ajax

    1. 后台改造:

        将自动排课功能的接口分为两个:redis

            ①建立线程执行自动排课app

            ②提供接口查询排课结果post

        对原有的方法进行改造:原有的方法,方法执行完成后才会返回执行结果。时间过长,考虑将原方法改造为线程执行,这样一旦线程开始执行,就能够返回结果。this

 

        改造方法:spa

  • 自动排课功能所在的service类实现Runnable接口,将自动排课的实现逻辑写在run方法中。
  • 编写方法①建立并执行线程,执行run方法。
  • Controller层调用方法①实现自动排课功能。
  • 对于自动排课结果,能够放在redis中,接口①实时更新自动排课的状态(成功或者失败),能够经过接口②每间隔一段时间查询自动排课的结果。

        

        代码示例:线程

Controller层

@Controller
public class Controller{

    @Autowired
    //自动注入排课功能所在的service
    private CourseTableService courseTableService; 

    @RequestMapping(value = "/arrange/{id}")
    @ResponseBody
    public ResponseMessage arrange(@PathVariable String id) {
        return courseTableService.arrange(id); //自动排课
    }

    @RequestMapping(value = "/arrangeResult/{id}")
    @ResponseBody
    public Map<String,Object> arrangeResult(@PathVariable String id) {
        //查询自动排课结果,并返回
    }
}

Service层

@Service
@Transactional(readOnly = true)
public class CourseTableService implements Runnable {  //实现Runnable接口
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor; //线程池  
 
    //自动paike
    public ResponseMessage arrange(String scheduleId) {
        this.scheduleId=scheduleId;  //设置run方法中须要用的参数
        taskExecutor.execute(this); //执行线程
        return ResponseMessage.ok(); //返回线程执行结果
    }
 
    //自动排课,线程
    public void run(){ 
        //排课逻辑代码
        String scheId=this.scheduleId; //使用接收的参数
    }
}

 

    2. 前端大体分两次请求后台接口:

    第一次请求接口自动排课(线程或者mQ执行),这样在启动自动排课的时候就返回请求结果,告知用户正在进行排课。

    而后轮询调用第二接口,每隔几秒钟就去查询排课的结果。若是返回的状态为0表明排课成功,提示用户;若是返回的状态为1达标排课失败,提示失败缘由;若是返回的状态为2表明排课正在执行中,继续轮询访问查询排课结果的接口。

    主要代码示例:

var intervalFlag=true; //是否执行轮询的标志
//_post2是封装的ajax请求,                
$._post2('/arrange/' + _id, {}, function(res) { 
    var interVal;
    //调用接口,查询自动排课结果,加上这个是为了用户点击后立马访问,ajax同步访问,
    //由于此次的查询结果决定了,是否执行轮询。
    getProgress(_id, interVal); 
    if(intervalFlag){
        //第一次查询结果代表排课还在进行中,才会执行轮询。
        //若是第一次已经返回结果表示程序执行完成,就不须要轮询访问排课结果了。
        interval(_id); 
    }
});

// 进度查询
function getProgress(_id, interVal) {
    $._post2('/arrangeResult/' + _id, {}, function(res) {
        if (res.arrangeStatus == 0) {
            //排课成功
            clearInterval(interVal); //清空轮询
            intervalFlag=false; //设置为不执行轮询
        }else if(res.arrangeStatus==1){
            //排课失败
            clearInterval(interVal);
            intervalFlag=false;
        }else if(res.arrangeStatus==2){
            //排课进行中,什么都不作
        }
   });
}

// 隔两秒访问
function interval(_id) {
    var pro;
    // 定时器
    var interVal;
    interVal = setInterval(function() {
        // 获取返回对象
        pro = getProgress(_id, interVal);
    }, 2000);
}
相关文章
相关标签/搜索