js 請求異常重連或斷線後聯網重連機制(ajax)
這個需求的應用場景是這樣的,在開發一個基於h5的移動app 時,在請求api 時出現請求的異常或者是請求中途網路中斷的情況,一旦出現問題則需要重新觸發某個點選事件或者開啟某個頁面。於是就想,遇到異常情況我們能不能讓請求自動重連,重新呼叫我們的資料。當然,一開始都是先看看網上的解決方案,但是找了好久沒找到合適的(也可能是自己沒找對關鍵詞,當時搜尋的是 “js斷網重連機制”)。既然沒有的話,就只好自己試一下了(要是哪位朋友有解決方案,希望可以分享一下)。
簡單的整理一下需要的流程:
>發起請求
>如果請求正常,判斷是否是期望的結果(這裡說一下,一般我們的app 可以直接接我們開發的 後臺 api,但是在做這個專案時有點不一樣,在app與api之間多了一個第三方,我們的請求需要請求到第三方(jsp程式),然後第三方再請求我們的真實介面,有點繞,不能代理,第三方在請求異常或者超時時也有他們自己的訊息返回,所以要做好判斷是否是我們的資料)
>如果資料是我們能 api 返回的 執行 ajax 回撥程式
>如果資料是第三方的異常資料 嘗試重連(我們的 api 沒問題的話,重新請求一般都是能得到資料的)
>如果請求異常 嘗試重連
思路是這樣,但具體實現還是有其它問題的。比如
1. 怎麼確認是哪個請求出異常並對該請求重連呢?
2.重連的回撥能否正常執行呢?
暫時不管上面兩個問題,本文的解決發難如下
>建立一個 temp 陣列來儲存請求的記錄,每一個呼叫 ajax 請求前都儲存好必要資訊:id(請求標識,標識不同的請求),url,data,callback,reloadtimes(重複請求次數) 。
>在請求進來時,判斷是否已經在 temp中,不在的話,先儲存到temp 中
>請求正常的話 從 temp 中移除
>請求異常的話,嘗試重連
前面說了這麼多,還是看看程式碼吧。
(function(window) { var temp = new Array(); function removeTemp(obj) { var id = obj.id; //將請求記錄從 temp 中去掉 for (var key in temp) { if (id == temp[key].id) { console.log("移除:" + temp[key].id); temp.slice(key, 1); break; } } } function reconnect(obj) { var id = obj.id; //這可以寫更多的重連邏輯,比如 每次重連間隔的時間增加 if (obj.reloadtimes == 10) { //將請求記錄從 temp 中去掉 removeTemp(obj); } else { obj.reloadtimes++; console.log(obj.id + " " + obj.reloadtimes + " 秒 後自動重新連結"); setTimeout(() => { request(obj.id, obj.url, obj.data, obj.callback); }, obj.reloadtimes * 1000); //每次間隔時間遞增 } } //請求 function request(id, url, data, callback) { let obj = { id: id, url: url, data: data, callback: callback, reloadtimes: 0 }; //判斷是否已經存在 快取中了,存在則跳過 let exist = false; for (let key in temp) { if (id == temp[key].id) { exist = true; obj = temp[key]; break; } } //不存在快取中則插入 if (!exist) temp.push(obj); $.get(url, data, res => { let _obj = obj; //判斷正常請求是否符合預期,這裡判斷結果內容是否大於XXX,實際上可以看情況處理 if (JSON.stringify(res).length > 5) { //移除記錄 removeTemp(_obj); callback(res); } else { //重連 reconnect(_obj); } }).error(e => { //重連 let _obj = obj; console.log(_obj.id + " 請求異常"); reconnect(_obj); //console.log(e); }); //console.log(temp); } window.request = request; }(window))
用的時候這樣用就行了
//請求測試
request("aaaaaaa", "data.html", {}, res => {
console.log(res);
});
request("bbbbbbbb", "data1.html", {}, res => {
console.log(res);
});
request("ccccc", "data1.html", {}, res => {
console.log(res);
});
ps:這裡的id 是隨便寫的 aaaaa 什麼的,但實際開發的話,我們使用了 時間戳來作為id效果如圖
然後回頭看下那兩個問題
1.本文是通過建立一個物件陣列儲存了請求的必要資訊,滿足請求以及回撥所需引數。
2.這個一開始擔心的是多頁面共同呼叫一個請求,要是切換到另一個頁面會不會有問題,經實踐發現沒有問題(app 用的是 Hbuilder 開發)
ps:這裡處理的是 ajax請求的,但是 如果不用ajax 不知道能否實現呢?還有就是,百度pc 端檢索如果斷網會定期請求重連,但處理方式好像不一樣,哪位朋友瞭解的話,希望能分享一下,謝謝啦!