У меня есть функция JavaScript, которая довольно долга и выполняет много задач, я хотел бы сообщить о продвижении к пользователю путем обновления содержания элемента ПРОМЕЖУТКА с сообщением, когда я иду. Я пытался добавить document.getElementById ('spnProgress') .innerText =... операторы всюду по функциональному коду.
Однако, пока функция выполняется, UI не обновит и таким образом, Вы только когда-либо будете видеть последнее сообщение, записанное в ПРОМЕЖУТОК, который не очень полезен.
Мое текущее решение состоит в том, чтобы разбить задачу во многие функции, в конце каждого, который я установил сообщение ПРОМЕЖУТКА и затем "инициировал" следующее с вызовом window.setTimeout с очень малой задержкой (скажите что 10 мс). Это приводит к управлению и позволяет браузеру перекрашивать ПРОМЕЖУТОК с обновленным сообщением прежде, чем запустить следующий шаг.
Однако я нахожу это очень грязным и трудным следовать коду, я думаю, что должен быть лучший путь. У кого-либо есть какие-либо предложения? Там какой-либо путь состоит в том, чтобы вынудить ПРОМЕЖУТОК перекрасить, не имея необходимость оставлять контекст функции?
Спасибо
То, как вы это делаете, является правильным (на данный момент это может измениться по мере появления и принятия стандартов [см. Эндрю Айлетт ответ ], но пока не скоро). Вы должны уступить так, чтобы браузер мог обновлять пользовательский интерфейс. Я обнаружил, что чем больше я так думаю, тем чище становится, но мои первые несколько попыток сделать это действительно были довольно «беспорядочными». Надеюсь, вы найдете то же самое, когда к этому привыкнете.
Не знаю. Вы можете разбить свой код таким образом, чтобы отдельные функции могли совместно использовать переменные, таким образом:
var a = some_local_state();
runTasksWithProgress([
function() {
do_some_work(a);
a = a + 1;
},
function() {
do_some_other_work(a);
a = a * 2;
},
...
]);
runTasksWithProgress немного сложнее. По сути, вы вызываете первую задачу, обновляете статус, а затем настраиваете обратный вызов для выполнения последующих задач.
Этот подход может частично облегчить боль.
Это все равно, что спросить, можно ли прервать процедуру, не прерывая ее. Ответ - нет. Вы должны использовать setTimeout () или setInterval (), чтобы передать управление механизму рендеринга браузера.
Если вы используете setInterval (), вы можете запустить этот процесс, а в вашей выполняемой функции просто обновите внешнюю переменную, которая будет опрашиваться функцией, вызываемой setInterval (). Таким образом, вам нужно сделать только один вызов вместо того, чтобы делать их в цикле.
Если у вас есть контроль над целевым браузером, вы можете использовать Рабочий поток HTML5 для выполнения работы в фоновом режиме.
Вы должны знать, что в некоторых браузерах вы получите сообщение о тайм-ауте скрипта, если у вас есть долго работающий скрипт. Так что на самом деле желательно разделить это с помощью таймера.
Сказав это, если вы ищете действительно структурированный способ сделать это, вы можете посмотреть библиотеку фоновых задач, которую я написал для проекта проверки орфографии. Это позволяет вам реализовать отображение / сокращение для массивов данных по таймеру.
Что-то вроде этого может сработать, если ваша функция выполняется в цикле. Он проверяет соответствие количество времени, которое прошло, и обновляет индикатор выполнения, если прошло 1/2 секунды. (Пример не тестировался. Возможно, вам придется немного поиграть с ним.)
var start;
function longRunning(lastState){
start = (new Date);
for(var i = lastState; i < 1e6 /*= 1000000 iterations */; ++i){
if((new Date)-start<500){
// do your stuff;
}
else{
// call a function to update the progress bar
updateProgressBar();
// continue the loop...
setTimeout(function(){longRunning(i);},13);
break;
}
}
}
longRunning(0);