2016-05-27 3 views
-1

Я это внутри функции АЯКСJQuery Каждый не дожидаясь функции внутри, чтобы закончить

$.each(data['Result'][0], function(Key, Value) { 
    InputGen(Value['Type'], Value['Name'], Value['Other'], Value['Value'], function(Html){ 
     Table = Table + "<tr><td>"+Key+"</td><td>" + Html + "</td></tr>"; 
    }); 
}); 

и InputGen имеет функцию обратного вызова из другой функции AJAX, но не кажется, ожидая, когда я запускаю этот цикл ajax для завершения. как я могу это достичь?

+0

Вам понадобится какая-то система ожидания или обещания. –

+1

AJAX - * асинхронный *. Ничто не собирается * ждать *, чтобы закончить. Обратный вызов будет запущен в будущем в какой-то момент, когда вызов будет выполнен. К тому времени ваш '$ .each' (и код после) уже давно сделан. –

ответ

2

Это потому, что AJAX асинхронный. Ничто не собирается подождать для этого. Обратный вызов будет запущен в будущем в какой-то момент, когда вызов будет выполнен. К тому времени ваш $.each (и код после) длинный.

Решение здесь заключается в использовании обещаний. Таким образом, вы можете выполнить обратный вызов один раз все звонки AJAX завершены.

Вы можете использовать jQuery's $.Deferred для этого. Не редактируя функцию InputGen(), вы можете сделать что-то вроде этого:

var promises = []; 

$.each(data['Result'][0], function(Key, Value) { 
    var d = new $.Deferred; 

    InputGen(Value['Type'], Value['Name'], Value['Other'], Value['Value'], function(Html){ 
     d.resolve([Key, Html]); 
    }); 

    promises.push(d.promise()); 
}); 

$.when.apply($, promises).done(function(){ 
    for(var i=0, length=arguments.length; i < length; i++){ 
     var ele = arguments[i], 
      Key = ele[0], 
      Html = ele[1]; 

     Table = Table + "<tr><td>"+Key+"</td><td>" + Html + "</td></tr>"; 
    } 

    // In here is where you can use your updated `Table` variable. 
    // You *cannot* use it outside of here, since it was not updated yet 
}); 
+1

Мне нравится это решение, потому что оно позволяет перекрывать вызовы ajax. –

2

... петля, похоже, не ждет завершения ajax.

Нет, потому что "а" в "Аякс" означает асинхронных; это не происходит, когда вы совершаете вызов, это происходит позже. Но нет причин, по которым петля $.each знала, чтобы сидеть и ждать, пока она закончится.

Если вам это не нужно (например, для вызовов ajax накладываться нормально, что обычно должно быть, если они не полагаются друг на друга), look at Rocket Hazmat's approach.

Если вам нужен каждый вызов ajax, ожидающий окончания предыдущего, вы не сможете использовать $.each (или, по крайней мере, не так, как вы были); вместо этого использовать индекс и реагировать на обратный вызов, вызывая следующий запрос:

// Start with first entry 
var index = 0; 
var array = data['Result'][0]; 

// Do the first request 
doRequest(); 

function doRequest() { 
    var value = array[index]; 
    InputGen(value['Type'], value['Name'], value['Other'], value['Value'], function(Html) { 
     Table = Table + "<tr><td>"+index+"</td><td>" + Html + "</td></tr>"; 
     // This request is done, move to the next if any 
     if (++index < array.length) { 
      doRequest(); 
     } 
    }); 
} 

Side Примечание: Всецело в JavaScript, переменные и функции без конструктора названы, начиная с строчной буквы: value а не Value и т. д. Поэтому я использовал index, array и value выше.

Боковое примечание 2: value['Type] можно более просто написать как value.Type. (И так далее.)

Смежные вопросы