JS中如何處理多個ajax併發請求?
js中的多併發處理。
通常 為了減少頁面載入時間,先把核心內容顯示處理,頁面載入完成後再發送ajax請求獲取其他資料
這時就可能產生多個ajax請求,為了使用者體驗,最好是傳送並行請求,這就產生了併發問題,應該如何處理?
(1)並行改序列
如果業務邏輯和使用者體驗允許的情況下,可以改為序列,處理起來最簡單
function async1(){
//do sth...
async2();
}
function async2(){
//do sth...
}
async1();
(2)回撥計數
function async1(){
//do sth...
callback();
}
function async2(){
//do sth...
callback();
}
function callback(){
cnt++;
if(2==cnt) console.log('都已執行完畢');
}
(3)迴圈非阻塞
function async1(){
//do sth...
cnt++;
}
function async2(){
//do sth...
cnt++;
}
var interval = setInterval(function(){
if(2===cnt){
console.log('已執行完成');
clearInterval(interval)
}
};
這個方法採用了定時間隔觸發器,佔用CPU比較多,建議酌情使用
(4)jquery
使用jquery的延時處理方法,每個ajax請求完成後,把對應的Deferred置為完成狀態,然後用jquery判斷全部完成後再進行後續處理
var d1 = $.Deferred();
var d2 = $.Deferred();
function async1(){
d1.resolve( "Fish" );
}
function async2(){
d2.resolve( "Pizza" );
}
$.when( d1, d2 ).done(function ( v1, v2 ) {
console.log( v1 + v2 + '已完成');
});
另:ajax時非同步請求不會出現堵塞情況。
$.when($.ajax, $ajax).done(function() { balabala })
轉載:
經常在寫程式碼的時候碰到這樣的場景:頁面初始化時顯示loading頁,同時啟動多個ajax併發請求獲取資料,當每個ajax請求返回時結束loading。
舉個例子,一個下訂單的頁面,要查詢常用地址資訊、商品資訊、地市資訊…而這些請求都是非同步的,希望等到所有資料載入完成後再允許使用者操作。
要實現這個場景容易碰到的一個問題就是多併發怎麼控制?下面是一些解決方法和思路:
並行改為序列
如果業務邏輯本身是序列的,但是提供的請求方式又是非同步的,可以考慮此方法。
但本場景顯然不是這種情況,這樣做大大降低了頁面效能,延長了載入速度。
回撥
只適合併發數少的情況,多層巢狀回撥會讓程式碼的可讀性大大降低
- function async1(){
- //do sth...
- }
- function async2(){
- //do sth...
- async1();
- }
- async2();
ajax改為同步
如在jquery中將async引數設定為false。
Java程式碼
- $.ajax({
- url:"/jquery/test1.txt",
- async:false
- });
設定結束標識
簡單一點的可以設定計數器,每完成一個非同步函式加1,或者設定一個數組,每執行完一個非同步函式更新陣列。
回撥計數
Js程式碼
- var cnt = 0;
- function async1(){
- //do sth...
- callback();
- }
- function async2(){
- //do sth...
- callback();
- }
- function callback(){
- cnt++;
- if(2==cnt) console.log('都已執行完畢');
- }
迴圈阻塞
Java程式碼
- var cnt = 0;
- function async1(){
- //do sth...
- cnt++;
- }
- function async2(){
- //do sth...
- cnt++;
- }
- while(2>cnt){}
迴圈非阻塞
不建議過多使用,以免影響效能
Js程式碼
- var cnt = 0;
- function async1(){
- //do sth...
- cnt++;
- }
- function async2(){
- //do sth...
- cnt++;
- }
- var interval = setInterval(function(){
- if(2===cnt){
- console.log('已執行完成');
- clearInterval(interval)
- }
- }, 0);
第三方框架實現
jquery
目前我在專案中採用的方式
Java程式碼
- var d1 = $.Deferred();
- var d2 = $.Deferred();
- function async1(){
- d1.resolve( "Fish" );
- }
- function async2(){
- d2.resolve( "Pizza" );
- }
- $.when( d1, d2 ).done(function ( v1, v2 ) {
- console.log( v1 + v2 + '已完成');
- });
angular
具體程式碼不寫了,可以參考API文件中關於$watch的說明。