簡體   English   中英

jQuery / JavaScript回調,模式對話框

[英]JQuery / JavaScript callbacks, modal dialog

我試圖用通用術語來表達它,以使其更易於理解。 請理解,這是概念,而不是我要克服的特定示例。

好的,所以我有一些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);
}

我還做了第二個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(){
            setTimeout(function(){
                var orderItem = GetOrderItem(this); //ignore this function's implementation
                orderItems.push(orderItem);
            },500);
        });
        return orderItems;
    },0);
}

提前致謝!

您將必須異步執行此操作。 沒有其他方法可以刷新用戶界面。 請參閱此相關問題 這意味着您的調用代碼將必須更改為:

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

至:

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

大概,您只能通過使服務器請求同步從而阻塞瀏覽器等方式來避免使用此同步代碼。如果您打算陷入異步狀態,則不妨充分利用所有這些優勢。潛在的好處。 例如,您的模態可以更新以指示還有多少訂單需要下載:

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);
            }
        });
    }
}  

如果在單個服務器跳閘之前顯示對話框,則除非您期望用戶采取措施(例如,“ OK按鈕),否則這沒有任何意義。 這是因為在dialog()調用之后的代碼將繼續執行,而不管對話框的效果如何。

如果要通知他們進度,則必須在每次發出服務器請求時更新對話框。

在這種情況下,不能忽略函數GetOrderItem(this) 如果是AJAX調用,則其父方法GetOrderItems()的其余部分將在AJAX調用完成之前繼續執行。

因此,您將必須執行以下操作:

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);
        }
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM