2011-08-08 19 views
13

私は、n個のグループでajax呼び出しを行う方法を知りたいと思います。私が使用データを表示するテーブルを持っているjQueryでajaxリクエストのバッチを作成するにはどうすればよいですか?

は、ここに私のユースケースです。各行にドリルすることができます。各行に共通の属性がある場合は、より深くドリルすることができます。一度にすべてのドリルにドリルすることもできます。各行に対して、表に追加するデータをフェッチするためのajax呼び出しが行われます。

ある場合には、同時にドリルインするには最大50の行が存在することがあります。あなたが想像しているように、それはサーバーに多くのストレスを与えます。これらのコールは、発射前にバッチを待機する小規模のバッチでどのように送信するのが最適でしょうか?

私は潜在的に私を助けることができるjqueryメッセージキューイングのようなプラグインがあることを知っていますが、これは作業プロジェクトですので、可能な限りプラグインを避けたいと思います。

+1

ので、独自のキューマネージャを作る:) –

+0

この答えは、一般的にhttp://stackoverflow.com/questions/42425885/trying-to-make-2-ajaxを支援します42426722#42426722 –

答えて

16

もう一つの方法は、呼び出しは、まだ非同期ですが、AJAX呼び出しがまだ次のように各行の成功イベント待ちとなるよう、あなたのJavaScriptで再帰を使用することですjQuery.whenを使用すると、すべての要求が完了したときにコールバック関数を実行できます。

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3")) 
.done(function(data1, data2, data3){ 
     // Do something with the data 
}); 

それとも

$.when($.ajax("request1"), $.ajax("request2"), $.ajax("request3")) 
.then(successCallback, errorHandler); 

詳細については、以下のpostを参照してください。

また、プラグインを使用することに対するあなたの懸念が、作業環境にあるという事実、特に作業を簡略化する場合、影響を受けているかどうかはわかりません。したがって、生産性を高めることができます。品質と長期的なメンテナンスが問題になる可能性があるため、プラグインを慎重に選択しなければならないと認めています。

+1

jQuery [Deferredオブジェクト](http://api.jquery.com/category/deferred-object/)は、確実に非同期要求を処理する方法です。 $ .ajax約束オブジェクトとsetTimeoutによって生成されたコードを扱うときに$ .whenと$ .doneを使用すると、コードがより洗練されて読みやすくなりました。いいですよ。 – stinkycheeseman

+0

はい、$ .when()を理解していますが、5K xhr2のクエリである私のケースでは厄介なように見え、50のバッチが送信されました(ChromはSPDYサーバーでメモリ障害をスローします)、Chromiumの人々は最終的に修正しますが、今。私は以下の再帰の提案を試してみるかもしれないと思う。それは正しいと思いますか? –

7

jQueryを使用したAjax呼び出しは、通常は非同期です。したがって、50行がある場合、jQueryは非同期で50個のリクエストをすべて送信します。サーバーからの応答を受け取ったときに処理の順序を制御することはできません。

あなたが唯一の要求はあなたの行をあなたのループとしてサーバーに送信されるように $.ajaxコールに async: falseを使用することができます

$.ajax({ 
    url: location, 
    data: params, 
    async: false, 
    success: function(msg) { // do something} 
}); 

このアプローチ(async: false)の問題は、ユーザーが経験するかもしれないということです「フリーズ」または応答しないページ。あなたが見てみることができ

var maxRows = 50; 

function myFunc(index) { 
    $.ajax({ 
     url: location, 
     data: params, 
     async: true, 
     success: function(msg) { 
      if (index < maxRows) { 
       // do something 
      } 
      else { 
       return; //index equals maxRows--stop the recursion 
      } 
      index++; 
      myFunc(index); //call the function again 
     } 
    }); 

    $(document).ready(function() { 
     myFunc(0);  
    }); 
} 
+0

5K xhr2のクエリを実行し、50のバッチを送信する必要があります(ChromeはSPDYサーバーでメモリ障害をスローします)。クロムの人々は最終的に修正する予定ですが、今は調整が必要です。あなたの再帰的アプローチは有望だと思います。 –

3

私はeictoに同意します:別のメッセージマネージャーを統合できない場合は、独自のメッセージマネージャーを作成してください。

var AjaxQueue = function(max) { 
    this.max = max; 
    this.requests = []; 
    this.current = 0; 
} 

AjaxQueue.prototype.ajax = function(opts) { 
    var queue = this; 
    opts.complete = function(jqXHR, textStatus) { 
    queue.current -= 1; 
    queue.send(); 
    }; 
    this.requests.push(opts); 
    this.send(); 
} 

AjaxQueue.prototype.send = function(opts) { 
    while (this.current < this.max && this.requests.length > 0) { 
    $.ajax(this.requests.unshift()); 
    this.current += 1; 
    } 
} 

私はまだそれを使用しようとしていないので、バグがあります。また、completeオプションを使用していないことを前提としています。それは単にそれを上書きします。もしあなたがそれをチェックし、前の完全な機能がまだ呼び出されていることを確認することができます。

+0

これは完璧です。私はそれで遊んで、私ができることを見ていきます。私の唯一の懸念は、this.currentに競合状態の可能性があるということですか?私は2つのAjaxが同時に完了することはまれであることを知っています。だから考える価値はありますか? – stinkycheeseman

+2

いいえ。ブラウザは、2つのユーザー定義関数を同時に実行できないようにします。このため、無限のwhileループを実行すると、Webページとのやりとりがロックされます。それは事をより簡単にします。 –

+0

使用例がありますか? – PlanetWilson

0

呼び出しの再帰的なバッチ処理は私の仕事です。しかし、私は4KのXHR2ブロブを取得しており、それぞれをIndexedDB(PouchDB)に保存しています。私はXHR2とIDBの両方にスレッドを持っています。だから私は、もう少し洗練されなければなりませんでした:

 for (var i in info.LayerInfo) { 
     var imageType = (info.LayerInfo[i].Class == "BASE") ? "jpg" : "png"; 
     info.LayerInfo[i].SaveCount = 0; 
     getLayer(0, info, info.LayerInfo[i], info.LayerInfo[i].Path, imageType); 
    } 
} 

function getLayer(index, info, layer, base, imageType) { 
    if (layer.Files.length == 0) { 
     console.log("Thread done: " + index + " SaveCount: " + layer.SaveCount); 
     return; 
    } 
    var val = layer.Files.shift(); 
    var path = base + "/" + val.id + "." + imageType; 
    $xhr.ajax({ 
     url: path, 
     dataType: "blob", 
     success: function (data) { 
      console.log("fetched: ", layer.Type + "-" + val.id); 
      saveBlob(data, val.size, val.id, layer.Type, index, info, layer, base, imageType); 
      if (index < maxThreads - 1) { 
       getLayer(++index, info, layer, base, imageType); 
      } else { 
       return; 
      } 
     } 
    }); 
} 

function saveBlob(blob, length, id, layerID, index, info, layer, base, imageType) { 
    if (blob.size != length) { 
     console.error("Blob Length found: ", blob.size, " expected: ", length); 
    } 
    var blobID = layerID + "-" + id; 
    var type = blob.type; 
    DB.putAttachment(blobID + "/pic", blob, type, function (err, response) { 
     if (err) { 
      console.error("Could store blob: error: " + err.error + " reason: " + err.reason + " status: " + err.status); 
     } else { 
      console.log("saved: ", response.id + " rev: " + response.rev); 
      layer.SaveCount++; 
      getLayer(index, info, layer, base, imageType); 
     } 
    }); 
} 
関連する問題