最近在開發微信小程序, 在測試時, 總能碰到一些諸如網絡被打斷啊之類的問題. 小程序是一款實時互動的小程序, 基於一系列緣由, 沒有使用Socket, 而是使用的是長連接. 因此對這類問題不能大意啊, 一個請求斷了, 後面的實時狀態就無從談起了.javascript
最簡單的啊, 就是對這個長連接捕獲錯誤, 而後重試唄! 固然, 實現這個很簡單, 沒兩行代碼就搞定了. 我還作了斷網之類的驗證, 單單規避這個長連接的錯誤, 徹底OK的.java
可是還有不少其餘請求哇, 作斷網重連的測試的時候, 能致使一些其餘未知的影響(固然,不斷網的狀況下這些是不存在的), (我的處女座, 追求完美)因而我就決定從網絡請求的底層, 寫入重試機制.小程序
整個項目是Web短和小程序端的實時互動, 爲了公用一套類庫, 我對全部Web和小程序端的底層接口都作了封裝, 以達到公用類庫的目的, 而重試機制我只準備給小程序作, Web端是內部使用的, 出現極端狀況, 讓他刷新一下咯, 並且這種機率很小, 就不考慮了.微信小程序
首先描述一下個人重試機制的思路, 當任何一個請求發生錯誤以後, 進行捕獲, 進行十次重試, 每次的時間間隔都比上次長, 十次以後, 提示用戶網絡故障是否要重試, 用戶點是以後會再次重試十次, 依次規律, 直至網絡請求成功.promise
const _retryTimes: number = 10; class JeResolve { protected promise: Promise<NetRes<any>> protected _resolve: (value: NetRes<any>) => void | PromiseLike<void>; protected _reject: (reason: any) => void; protected reqOptions: RequestOptions; protected requestObj: RequestTask; protected Listener: JeSysListener = new JeSysListener(this); constructor() { this.promise = new Promise((resolve, reject) => { this._resolve = resolve; this._reject = reject; }); } request<T>(options?: RequestOptions | undefined): IResolve<T> { if (options) { this.retryTimes = 0; options.url = commonService.getUrl(options.url); this.reqOptions = options; this.reqOptions.success = (res: any) => { this.Listener.UnListen(); this._resolve(res); }; this.reqOptions.fail = (res: any) => { if (this.retryTimes < _retryTimes) { this.retryTimes++; if (!this.isAbort) { setTimeout(() => { if (this.retryTimes < _retryTimes + 1 && !this.isAbort) { this.requestObj = uni.request(this.reqOptions); } }, 100 * this.retryTimes); } } else { systemService.raiseRetryTimedout(); } }; this.requestObj = uni.request(this.reqOptions); } return this; } resolve<T>(call: (res: T) => void): IAbort { this.promise.then(res => { call(res.data); }); return this; } abort() { this.Listener.UnListen(); this.requestObj.abort(); this.isAbort = true; } protected retryTimes: number = 0; protected isAbort: boolean = false; onRetryedSuccess(event: SysEvent): void { this.retryTimes = 0; this.requestObj = uni.request(this.reqOptions); } onRetryedTimesout(event: SysEvent): void { this.retryTimes = _retryTimes; } }
以上是我基於Promise本身封裝的請求類, 上面很容易看懂, 最底下兩個方法解釋一下, 是本身分封裝的全局的事件的觸發以及監聽.
主要邏輯:
一、當某個請求重試超過十次以後觸發請求超時的事件, 全局會對事件進行一個過濾, 上次事件沒有被用戶反饋以前, 多個請求接連觸發超時會自動過濾掉.
二、在用戶點擊肯定重試以後, 會觸發一個肯定重試的事件, 全部失敗的請求都能監聽到這個事件, 開始新的十次重試.
以爲這個挺好玩的, 才寫出來, 還不夠完善, 感興趣的道友批評指正.微信