ajax調用接口數據錯亂的原因及解決方法

        前段時間在做項目的時候遇到一個問題,在開發webapp的時候使用ajax調用後端接口的時候,出現了接口數據錯亂的問題,現在總結一下

問題描述:

        同一個頁面同時調用多個接口:A、B、C、D、E,正常返回結果應該是A-a, B-b, C-c,D-d,E-e。在網絡環境比較好的時候,沒有問題,然而,在網絡環境比較差的時候,錯誤出現了。返回結果中至少有兩個接口返回的結果被其他接口的數據覆蓋,結果變成了A-a, B-c, C-c,D-e,E-e,或者A-b, B-b, C-b,D-d,E-e ...... 結果被覆蓋的情況完全隨機,每次都可能不一樣,相同的是每次都會錯亂。

        當時第一反應是前端ajax併發導致數據錯亂,因爲之前自己寫PC端和移動端網頁的時候(對,不稱職的全棧就是我)調用的接口是一樣的,沒有出現過類似的問題,而現在的webapp是由新入職的前端小哥(不是小白,是資深前端)來做的,新人來了,出現新的問題,那一定是新人這邊的問題,所以果斷甩鍋過去。

        結果前端小哥表示自己也是首次遇到同樣的問題,找了很多資料也百思不得其解,我也認爲這肯定是前端的問題就沒有細查,這個問題就一直懸而未決,直到我忙完了其他事情,前端小哥還沒有找出問題,沒法海得我自己來了。

開始定位問題

        問題在前端,那就從前端開始,寫一個測試頁面,請求路徑爲我們的測試服:


查看控制檯,結果:錯亂,和之前的錯誤預估一樣,網絡環境差的時候,數據錯亂

沒有對比就沒有發言權,所以這次把請求路徑變爲自己的開發環境:


查看控制檯,結果竟然還是錯亂,這個問題首次在本地重現了,ok,至少進了一步。

再看看是不是偶然事件,於是多刷新幾遍,結果無一例外的全部是數據錯亂

之前直接甩鍋到前端,因爲前端用的框架和我之前用的框架不一樣,爲了確定是不是框架的原因,我特意直接用jQuery寫ajax調用接口,看來框架的原因可以排除了

排除了前端的問題,那就是後端接口的問題了,然後我開始查接口的實現方法,突然發現一個可能的問題,後端使用SpringMVC,所有接口都繼承自同一個Controller

......
......
/**
 * 通用工具類
 * @author heh
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class BaseController {
	
	......
	......
	
	/**
	 * 提示(用於返回操作結果)
	 */
	protected Tip tip = new Tip();

	......
	......	
}

然後所有的接口都統一使用這個tip作爲數據容器然後返回數據,是這樣寫的

......

@Controller
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
public class WSControllerImpl extends BaseController implements ...... {

	......

	@Override
	public Tip getUserMessage(HttpServletRequest req) {
		String messageid = req.getParameter("id");
		tip.success(userService.getMessageById(messageid));
		return tip;
	}
	
	......

}

之前爲了減少重複代碼,就把這個tip容器放到了BaseController裏,供其子類調用,沒有考慮到不同接口調用這個公共參數的時候,不是獨佔調用,而是所有的接口都可以修改,所以多個接口同時調用的時候,就會出現A接口調用完畢,還沒有返回的時候,tip已經被B接口修改了,所以造成A接口返回的數據和B接口返回的數據變成一樣的情況。至此確定了問題。

問題確定之後,解決就簡單了,只要讓每個接口的tip單獨new出來即可,不使用公共資源

回顧確定問題的過程,發現多接口併發執行的時候,少於4個接口的時候不會錯亂,大於或等於4個接口的時候,問題必然出現。這也算是一個低級錯誤了。


總結:在多個子類訪問同一個父類的資源的時候,數據類資源最好是不可更改的類型,不要讓多個子類同時修改父類的內容。父類的公用內容儘量使用工具操作類的代碼,不要用數據共享的內容。代碼還是要踏踏實實寫,偷懶很容易出問題。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章