2011-12-08 18 views
0

私はこれを一般的な用語に置き換えて、わかりやすくしました。私が克服しようとしている具体例ではなく、それがコンセプトであることをご理解ください。JQuery/JavaScriptコールバック、モーダルダイアログ

OK、オブジェクトを取得するためにサーバーにコールするJavaScriptがあります。注文には、注文アイテムIDの配列を含むプロパティがあります。私が言ったのIDをループし、その後をしたいと注文アイテムレコードを取得し、配列にそれらを返す、このような:

function GetOrderItems(orderId){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    $.each(orderItemIDs, function(){ 
     var orderItem = GetOrderItem(this); // ignore this function's implementation 
     orderItems.push(orderItem); 
    }); 
    return orderItems; 
} 

問題は、かなりの数の注文項目があるかもしれないということですが、私はそれらを取得する必要がありますサーバー1から一度に(尋ねないで、これは変更されません)。そこで、jQuery UIのモーダルダイアログを使用して、いくつの注文があるかを知りたいので、どれくらい時間がかかるか考えています。だから、私はラインを以下に記す注入しよう:

function GetOrderItems(orderId){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    $("#modalDiv").dialog({title: orderItemIDs.length + " order items to get."}); 
    $.each(orderItemIDs, function(){ 
     var orderItem = GetOrderItem(this); // ignore this function's implementation 
     orderItems.push(orderItem); 
    }); 
    return orderItems; 
} 

問題は、ダイアログを示していることですが、すべてがすべて完了した場合のみです。以前の質問から、setTimeoutを使用してモーダルを表示する方法を学んだが、構築している配列を返すにはどうすればよいですか?

function GetOrderItems(orderId){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    $("#modalDiv").dialog({title: orderItemIDs.length + " order items to get."}); 
    setTimeout(function(){ 
     $.each(orderItemIDs, function(){ 
      var orderItem = GetOrderItem(this); //ignore this function's implementation 
      orderItems.push(orderItem); 
     }); 
     return orderItems; 
    },0); 
} 

私も進行状況を表示するために、第2のsetTimeout関数をやってきましたが、それは最後の1に直進し、機能のどれもが、このように、実行します。

function GetOrderItems(orderId){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    $("#modalDiv").dialog({title: orderItemIDs.length + " order items to get."}); 
    setTimeout(function(){ 
     $.each(orderItemIDs, function(){ 
      setTimeout(function(){ 
       var orderItem = GetOrderItem(this); //ignore this function's implementation 
       orderItems.push(orderItem); 
      },500); 
     }); 
     return orderItems; 
    },0); 
} 

感謝を事前に!

+0

を、しかし、と述べているときは、同期機能として扱うていますサーバーからデータを取得しています。これはあなたが抱えている問題の根源になりそうです。 – nrabinowitz

答えて

1

これを非同期で実行する必要があります。 UIをリフレッシュさせる他の方法はありません。 See this related question。このように、おそらく

GetOrderItems(orderId, function (orderItems) { 
    // do something with orderItems 
}) 

、あなただけのサーバー要求が同期することによって、この同期コードで逃げることができました:へ

var orderItems = GetOrderItems(orderId); 
// do something with orderItems 

:それはあなたの呼び出し元のコードから変更する必要があります意味しますブラウザーをつないでください。もしあなたがasynchronocityに飛び込むのであれば、すべての潜在的な利点を活用するかもしれません。たとえば、あなたのモーダルがダウンロードされずに残っているどのように多くの受注を示すように更新することができます

function GetOrderItems(orderId, callback){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    var orderItemCount = orderItemIDs.length; 
    $("#modalDiv").dialog({title: "<span id=\"orderItemRemaining\">" + orderItemCount + "</span> order items to get."}); 
    $.each(orderItemIDs, function(){ 
     $.get("/getOrderItem?orderId=" + this, function (orderItem) { 
      orderItems.push(orderItem); 
      var remaining = orderItemCount - orderItems.length; 
      $("#orderItemRemaining").text(remaining); 
      if (!remaining) { 
       callback(orderItems); 
      } 
     }); 
    }); 
} 

編集:は、同時要求を制限するに$.each()を使用しないでください。代わりにあなたがしたいの同時要求の数だけを起動し、要求の成功ハンドラでリクエストの残りを開始:あなたは前にそれがない限り意味をなさない個々のサーバ旅行にダイアログを表示している場合

function GetOrderItems(orderId, callback){ 
    var orderItemIDs = GetOrderItemIDs(orderId); // array of order item IDs 
    var orderItems = []; 
    var orderItemCount = orderItemIDs.length; 
    $("#modalDiv").dialog({title: "<span id=\"orderItemRemaining\">" + orderItemCount + "</span> order items to get."}); 
    var maxConcurrent = 3; 
    for (var i = 0; i < maxConcurrent; i++) { 
     getOrderItem(orderItemIDs.shift()); 
    } 
    function getOrderItem(orderItemID) { 
     $.get("/getOrderItem?orderId=" + orderItemID, function (orderItem) { 
      orderItems.push(orderItem); 
      var remaining = orderItemCount - orderItems.length; 
      $("#orderItemRemaining").text(remaining); 
      if (remaining) { 
       getOrderItem(orderItemsIDs.shift()); 
      } 
      else 
       callback(orderItems); 
      } 
     }); 
    } 
} 
+0

これは非常に興味深いですが、サーバーへの同時リクエスト数をどのように制限できますか? –

+0

@JohnWilliams - 一度にリクエストを1つに制限するか、任意の制限に制限しますか? – gilly3

+0

後者が最適かもしれませんが、どちらかを取っていきます。前もって感謝します! –

0

をユーザーからの操作が必要です(たとえば、OKボタン)。これは、ダイアログの効果に関係なく、dialog()呼び出しに続くコードが引き続き実行されるためです。

進捗状況を通知する場合は、サーバーの要求が行われるたびにダイアログを更新する必要があります。

この場合、関数GetOrderItem(this)は無視できません。 AJAX呼び出しの場合、残りの親メソッドGetOrderItems()は、AJAX呼び出しが完了する前に実行を継続します。

ですから、このような何かする必要があります:あなたはGetOrderItemIDs`と `GetOrderItem``の実装を無視するために私達に言っている

var someGlobalCounter = 0; 

function GetOrderItem(item) { // gets called X number of times 
    $.ajax({ 
     ... 
     success: function(retrievedItem) { 
      someGlobalCounter++; 
      $('#modalDiv').html(someGlobalCounter + ' records retrieved so far...'); 
      orderItems.push(retrievedItem); 
     } 
    }); 
}