1. 程式人生 > >JS中如何處理多個ajax併發請求?

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。 
舉個例子,一個下訂單的頁面,要查詢常用地址資訊、商品資訊、地市資訊…而這些請求都是非同步的,希望等到所有資料載入完成後再允許使用者操作。 
要實現這個場景容易碰到的一個問題就是多併發怎麼控制?下面是一些解決方法和思路: 

並行改為序列
如果業務邏輯本身是序列的,但是提供的請求方式又是非同步的,可以考慮此方法。 


但本場景顯然不是這種情況,這樣做大大降低了頁面效能,延長了載入速度。 

回撥
只適合併發數少的情況,多層巢狀回撥會讓程式碼的可讀性大大降低 

Java程式碼 
  1. function async1(){  
  2.     //do sth...  
  3. }  
  4. function async2(){  
  5.     //do sth...  
  6.     async1();  
  7. }  
  8. async2();  

ajax改為同步

如在jquery中將async引數設定為false。 
Java程式碼 
  1. $.ajax({  
  2.     url:"/jquery/test1.txt",  
  3.     async:false  
  4. });  

設定結束標識
簡單一點的可以設定計數器,每完成一個非同步函式加1,或者設定一個數組,每執行完一個非同步函式更新陣列。 

回撥計數
Js程式碼 
  1. var cnt = 0;  
  2. function async1(){  
  3.     //do sth...  
  4.     callback();  
  5. }  
  6. function async2(){  
  7.     //do sth...  
  8.     callback();  
  9. }  
  10. function callback(){  
  11.     cnt++;  
  12.     if(2==cnt) console.log('都已執行完畢');  
  13. }  

迴圈阻塞 
Java程式碼 
  1. var cnt = 0;  
  2. function async1(){  
  3.     //do sth...  
  4.     cnt++;  
  5. }  
  6. function async2(){  
  7.     //do sth...  
  8.     cnt++;  
  9. }  
  10. while(2>cnt){}  

迴圈非阻塞

不建議過多使用,以免影響效能 
Js程式碼 
  1. var cnt = 0;  
  2. function async1(){  
  3.     //do sth...  
  4.     cnt++;  
  5. }  
  6. function async2(){  
  7.     //do sth...  
  8.     cnt++;  
  9. }  
  10. var interval = setInterval(function(){  
  11.     if(2===cnt){  
  12.         console.log('已執行完成');  
  13.         clearInterval(interval)  
  14.     }  
  15. }, 0);  

第三方框架實現
jquery

目前我在專案中採用的方式 
Java程式碼 
  1. var d1 = $.Deferred();  
  2. var d2 = $.Deferred();  
  3. function async1(){  
  4.     d1.resolve( "Fish" );  
  5. }  
  6. function async2(){  
  7.     d2.resolve( "Pizza" );  
  8. }  
  9. $.when( d1, d2 ).done(function ( v1, v2 ) {  
  10.     console.log( v1 + v2 + '已完成');  
  11. });  

angular

具體程式碼不寫了,可以參考API文件中關於$watch的說明。