1. 程式人生 > >js處理併發請求

js處理併發請求

1,Promise並行執行非同步任務

試想一個頁面聊天系統,我們需要從兩個不同的URL分別獲得使用者的個人資訊和好友列表,這兩個任務是可以並行執行的,用Promise.all()實現如下:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
// 同時執行p1和p2,並在它們都完成後執行then:
Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 獲得一個Array: ['P1', 'P2']
});

有些時候,多個非同步任務是為了容錯。比如,同時向兩個URL讀取使用者的個人資訊,只需要獲得先返回的結果即可。這種情況下,用Promise.race()實現:

var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
});
Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
});

由於p1執行較快,Promise的then()將獲得結果'P1'p2仍在繼續執行,但執行結果將被丟棄。

如果我們組合使用Promise,就可以把很多非同步任務以並行和序列的方式組合起來執行。

/* 先定義一個返回Promise物件的Ajax過程 */
var getAjaxPromise = function(option){
return new Promise(function(resolve, reject){
$.ajax({
url: option.url,
type: 'get',
data: option.data || '',
success: function(data){
resolve(data);
},
error: function(error){
reject(error);
}
});
});
};

/* 啟動第1個非同步任務 */
var p1 = getAjaxPromise({
url: 'root/url/1'
});

p1.then(function(data1){
/* 處理第1個非同步任務的結果 */
console.log(data1);

/* 然後啟動第2個非同步任務 */
return getAjaxPromise({
url: 'root/url/2'
});
})
.then(function(data2){
/* 處理第2個非同步任務的結果 */
console.log(data2);
});

ajax改為同步

如在jquery中將async引數設定為false

$.ajax({
url:"/jquery/test1.txt",
async:false
});

設定結束標識

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

回撥計數

var cnt = 0;
function async1(){
  //do sth...
  callback();
}
function async2(){
  //do sth...
  callback();
}
function callback(){
  cnt++;
  if(2==cnt) console.log('都已執行完畢');
}

迴圈阻塞

var cnt = 0;
function async1(){
  //do sth...
  cnt++;
}
function async2(){
  //do sth...
  cnt++;
}
while(2>cnt){}

迴圈非阻塞

不建議過多使用,以免影響效能

var cnt = 0;
function async1(){
  //do sth...
  cnt++;
}
function async2(){
  //do sth...
  cnt++;
}
var interval = setInterval(function(){
  if(2===cnt){
    console.log('已執行完成');
    clearInterval(interval)
  }
}

第三方框架實現

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 + '已完成');
});