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 ...... 結果被覆蓋的情況完全隨機,每次都可能不一樣,相同的是每次都會錯亂。
開始定位問題
問題在前端,那就從前端開始,寫一個測試頁面,請求路徑為我們的測試服:
檢視控制檯,結果:錯亂,和之前的錯誤預估一樣,網路環境差的時候,資料錯亂
沒有對比就沒有發言權,所以這次把請求路徑變為自己的開發環境:
檢視控制檯,結果竟然還是錯亂,這個問題首次在本地重現了,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個介面的時候,問題必然出現。這也算是一個低階錯誤了。
總結:在多個子類訪問同一個父類的資源的時候,資料類資源最好是不可更改的型別,不要讓多個子類同時修改父類的內容。父類的公用內容儘量使用工具操作類的程式碼,不要用資料共享的內容。程式碼還是要踏踏實實寫,偷懶很容易出問題。
前段時間在做專案的時候遇到一個問題,在開發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 ...... 結果被覆蓋的情況完全隨機,每次都可能不一樣,相同的是每次都會錯亂。
開始定位問題
問題在前端,那就從前端開始,寫一個測試頁面,請求路徑為我們的測試服:
檢視控制檯,結果:錯亂,和之前的錯誤預估一樣,網路環境差的時候,資料錯亂
沒有對比就沒有發言權,所以這次把請求路徑變為自己的開發環境:
檢視控制檯,結果竟然還是錯亂,這個問題首次在本地重現了,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個介面的時候,問題必然出現。這也算是一個低階錯誤了。
總結:在多個子類訪問同一個父類的資源的時候,資料類資源最好是不可更改的型別,不要讓多個子類同時修改父類的內容。父類的公用內容儘量使用工具操作類的程式碼,不要用資料共享的內容。程式碼還是要踏踏實實寫,偷懶很容易出問題。