调用接口处理时间过长,前端访问超时解决方案 - Go语言中文社区

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


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

    拿自动排课来说,如果一个学校上百个班级,执行一次排课可能需要1-2分钟甚至更长时间,那么会造成前台访问接口超时(当然也可以延长超时时间实现)。

解决方案:

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

    1. 后台改造:

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

            ①创建线程执行自动排课

            ②提供接口查询排课结果

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

 

        改造方法:

  • 自动排课功能所在的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);
}

 

转载于:https://my.oschina.net/u/3706132/blog/1550617

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_33830216/article/details/92401294
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-06-27 21:57:09
  • 阅读 ( 689 )
  • 分类:前端

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢