На этот вопрос нельзя ответить тем, что вы нам дали. Трудно найти исключение NullPointerException, если существует currentGroupModel, о котором мы ничего не знаем, и есть постоянные рыжие волосы. Например, почему вы храните что-то в ограниченном количестве, вы никогда не используете это! Почему вы передаете getTableRow rowIndex, который вы никогда не используете? Насколько я понимаю, ваш getTableRow возвращает последний TableRow в таблице, а не конкретный. Пожалуйста, подумайте об исправлении этих проблем, прежде чем в конечном итоге предоставить некоторый код, чтобы понять внутреннюю работу вашей currentGroupModel.
Вот решение:
function appendToSelect() {
$("#mySelect").children().remove();
$("#mySelect").html(
'<option selected value="'+obj.data[0].value+'">'
+ obj.data[0].name
+ '</option>'
);
obj.data.splice(0, 1); // we only want remaining data
var appendOptions = function() {
var dataChunk = obj.data.splice(0, 10); // configure this last number (the size of the 'chunk') to suit your needs
for(var i = 0; i < dataChunk.length; i++) {
$("#mySelect").append(
'<option value="' + dataChunk[i].value + '">'
+ dataChunk[i].name
+ '</option>'
);
}
if(obj.data.length > 0) {
setTimeout(appendOptions, 100); // change time to suit needs
}
};
appendOptions(); // kicks it off
}
Не так элегантно, как @ решение Боргара , но вы поняли идею. По сути, я делаю то же самое, но все в одной функции, а не разбиваю ее на функцию более высокого порядка, как он. Мне нравится его решение, но если нет, возможно, это сработает для вас.
РЕДАКТИРОВАТЬ: Для тех, кто не видит его сразу, одно из основных различий между этим решением и @ Borgar's заключается в том, что это решение позволяет вам устанавливать размер «чанков». данных, которые обрабатываются между каждым тайм-аутом. @ Тайм-аут Боргара после обрабатывается каждый отдельный элемент массива. Если у меня будет время, я постараюсь создать функцию более высокого порядка, чтобы она была более элегантной. Никаких обещаний! ;)
РЕДАКТИРОВАТЬ: Итак, вот моя адаптация решения @ Borgar , которое позволяет более легко устанавливать размер «чанка» и настраивать значение тайм-аута:
function incrementallyProcess(workerCallback, data, chunkSize, timeout, completionCallback) {
var itemIndex = 0;
(function() {
var remainingDataLength = (data.length - itemIndex);
var currentChunkSize = (remainingDataLength >= chunkSize) ? chunkSize : remainingDataLength;
if(itemIndex < data.length) {
while(currentChunkSize--) {
workerCallback(data[itemIndex++]);
}
setTimeout(arguments.callee, timeout);
} else if(completionCallback) {
completionCallback();
}
})();
}
function appendToSelect() {
$("#mySelect").children().remove();
$("#mySelect").html(
'<option selected value="' + obj.data[0].value + '">'
+ obj.data[0].name
+ '</option>'
);
obj.data.splice(0,1); // we only want remaining data
incrementallyProcess(function(data) {
$("#mySelect").append(
'<option value="' + data.value + '">'
+ data.name
+ '</option>'
);
}, obj.data, 10, 100, removeAnimatedGifFunction); // last function not required...
}
Надеюсь, что это помогает - я думаю, что это объединяет лучшее из обоих решений. Обратите внимание: вторая анонимная функция больше не использует значение индекса, а просто передает весь объект (со свойствами value и name); это делает его немного чище, поскольку индекс текущего объекта на самом деле не обычно , что полезно при итерации по вещам, IMO.
1113 Я уверен, что есть вещи, которые можно сделать, чтобы сделать это еще лучше, но это оставлено как упражнение для читателя. ;)
Это именно так происходит, который я отправлял об этом момент назад здесь . Вот синхронизированная функция цикла:
function processLoop( actionFunc, numTimes, doneFunc ) {
var i = 0;
var f = function () {
if (i < numTimes) {
actionFunc( i++ ); // closure on i
setTimeout( f, 10 )
}
else if (doneFunc) {
doneFunc();
}
};
f();
}
Для Вашей ситуации это использовалось бы как это:
function appendToSelect () {
$("#mySelect").children().remove() ;
$("#mySelect").html(
'<option selected value="' + obj.data[0].value + '">'
+ obj.data[0].name
+ '</option>'
);
var j = 1 ;
processLoop(function (i){
$("#mySelect").append(
'<option value="' + obj.data[i].value + '">'
+ obj.data[i].name
+ '</option>'
);
}, obj.data.length);
}
Вы захотите удостовериться, что у Вас есть закрытие или некоторый другой доступ к obj переменной в итеративной функции.
Hope это помогает.
Если вам нужно что-то более простое, я написал плагин jQuery для облегчения написания асинхронных циклов: jQuery Async .
Используя плагин, ваш код может быть переписан как:
function appendToSelect() {
$("#mySelect").children().remove() ;
$("#mySelect").html(
'<option selected value="' + obj.data[0].value + '">'
+ obj.data[0].name
+ '</option>'
);
/////////////////////////////
var i = 1;
$.whileAsync({
test: function(){ i < obj.data.length; }
loop: function()
{
$("#mySelect").append(
'<option value="' + obj.data[i].value + '">'
+ obj.data[i].name
+ '</option>'
);
i++;
}
});
/////////////////////////////
}
Должно помочь отзывчивость. Настройте параметры «bulk» и «delay» для большего контроля.
Необходимо было бы переписать функцию для кэширования списка элемента, затем цикл по списку с помощью какого-то счетчика.
Тогда, когда счетчик достигнет встречного % max_num_before_wait == 0, перезвоните тайм-ауту к самой функции.
Удостоверяются, что очистили кэш и счетчик в конце полного списка, или использовали вторичную функцию с дополнительным параметром количества.