[英]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.