Ответ 1
Вот решение:
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 решение, но вы получите эту идею. В принципе, я делаю то же самое, но все в вашей одной функции, а не разбиваю ее на функцию более высокого порядка, как он. Мне нравится его решение, но если вы этого не сделаете, возможно, это сработает для вас.
EDIT: для тех, кто этого не видит сразу, одним из основных различий между этим решением и @Borgar's является то, что это решение позволяет вам установить размер "кусков" данных, которые обрабатываются между каждым таймаутом. @Borgar's после каждого отдельного элемента массива обрабатывается. Если у меня будет время, я попытаюсь создать функцию более высокого порядка, чтобы справиться с этим, чтобы она была более элегантной. Нет promises, хотя!;)
EDIT: Итак, вот моя адаптация @Borgar's, которая позволяет более легко установить размер "chunk" и настроить значение тайм-аута:
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...
}
Надеюсь, что это поможет - я думаю, что это сочетает в себе лучшее из обоих решений. Уведомление, вторая анонимная функция больше не использует значение индекса, а просто передает весь объект (со значениями и свойствами имени); что делает его немного более чистым, так как индекс текущего объекта действительно не всегда полезен при итерации над вещами, IMO.
Я уверен, что все еще есть вещи, которые можно сделать, чтобы сделать это еще лучше, но это остается для упражнения читателем.;)