我遇到以下代码的问题:
jQuery.each正在加速,而不等待JSON请求完成。因此,'thisVariationID'和'thisOrderID'变量将被循环的最新迭代重置,然后才能在较慢的getJSON函数中使用。
有没有办法让.each的每次迭代等到getJSON请求和回调函数完成后才转到下一次迭代?
$.each($('.checkStatus'), function(){
thisVariationID = $(this).attr('data-id');
thisOrderID = $(this).attr('id');
$.getJSON(jsonURL+'?orderID='+thisOrderID+'&variationID='+thisVariationID+'&callback=?', function(data){
if (data.response = 'success'){
//show the tick. allow the booking to go through
$('#loadingSML'+thisVariationID).hide();
$('#tick'+thisVariationID).show();
}else{
//show the cross. Do not allow the booking to be made
$('#loadingSML'+thisVariationID).hide();
$('#cross'+thisVariationID).hide();
$('#unableToReserveError').slideDown();
//disable the form
$('#OrderForm_OrderForm input').attr('disabled','disabled');
}
})
})
答案 0 :(得分:3)
你需要使用其中之一 1)。非异步调用(如以下代码所示):
$.ajax({
url:jsonURL,
dataType:'json',
data:{orderID:thisOrderID, variationID:thisVariationID},
async:false,
success:function()
{
// do stuff.
}
2)。如果您正在使用jsonp跨站点,则需要链接您的呼叫而不是使用每个呼叫。使用each来构建一个数据数组,然后开始调用json,每次迭代都使用回调中之前的数据。
补充:为了澄清,一个跨站点实现,它设置要处理的项目列表,然后单独处理它们。
我已经进入了大多数普通的旧Javascript,在这种情况下认为更容易阅读:
var items = [];
function setUp()
{
items = []; // clear in case this gets recalled.
$('.checkStatus').each(function(idx, el){
values.push({variationID:$(el).data('id'), orderID:$(el).attr('id')});
}
if (items.length > 0)
{
consume();
}
}
function handleResponse(data)
{
// do your data handling and formatting here.
if (items.length >= 0) consume();
}
function consume()
{
var thisOrder = items.pop();
$.ajax({
url:jsonURL,
dataType:'jsonp',
data:{orderID:thisOrder.orderID, variationID:thisOrder.variationID},
async:false,
success:handleResponse
});
}
setUp();
请注意,尽管这些都位于全局命名空间中,但它们可以轻松地位于闭包或函数内(即将整个事物包装在$(document).ready()中)。
答案 1 :(得分:3)
快速解决方法有两个变化:
在变量之前使用var
使其成为本地而非全局变量。这样,您将为每个迭代获取新的变量实例。除非您真的打算污染全局命名空间,否则始终使用var
:
var thisVariationID = $(this).attr('data-id');
var thisOrderID = $(this).attr('id');
使用==
进行比较而不是=
;)
if (data.response == 'success'){
在解决您似乎忽略的这些问题后,您的代码很可能会按预期开始工作。但是,如果你愿意采取更激烈的改变,你也可以使用Deferreds。
要并行执行一堆提取:
var fetches = $('.checkStatus').map(function () {
var thisVariationID = $(this).attr('data-id'),
thisOrderID = $(this).attr('id');
return $.getJSON(/* blah blah */);
});
fetches = $.when.apply($, fetches);
fetches.done(function () {
// all parallel fetches done
});
序列化提取:
var fetching = $.when();
$('.checkStatus').each(function () {
var thisVariationID = $(this).attr('data-id'),
thisOrderID = $(this).attr('id');
fetching = fetching.pipe(function () {
return $.getJSON(/* blah blah */);
});
});
fetching.done(function () {
// last fetch done
});
过度破坏?也许。但它很灵活,有时可能值得使用代码的语法糖,字面意思是“当我的提取完成时”。
(注意:上述实现只是一个乐观的实现,仅用于说明目的。在实际实现中,您还应该处理失败。)
答案 2 :(得分:0)
您只需停用异步机制即可。 看看这里:https://stackoverflow.com/a/933718/1343096
答案 3 :(得分:0)
看我的评论我不知道为什么它去那里而不是回答。 这里它是同步的,所以它等待响应。
jQuery: Possible to wait for $.get to finish loading before continuing?