調用接口處理時間過長,前端訪問超時解決方案

    在項目中會遇到這樣的狀況,因爲後臺須要執行、計算一段時間(如計算積分、自動排課等)。這時前臺請求一段時間後,得不到返回結果就會發生請求超時。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);
}
相關文章
相關標籤/搜索