Как сообщить о прогрессе функции JavaScript?

У меня есть функция JavaScript, которая довольно долга и выполняет много задач, я хотел бы сообщить о продвижении к пользователю путем обновления содержания элемента ПРОМЕЖУТКА с сообщением, когда я иду. Я пытался добавить document.getElementById ('spnProgress') .innerText =... операторы всюду по функциональному коду.

Однако, пока функция выполняется, UI не обновит и таким образом, Вы только когда-либо будете видеть последнее сообщение, записанное в ПРОМЕЖУТОК, который не очень полезен.

Мое текущее решение состоит в том, чтобы разбить задачу во многие функции, в конце каждого, который я установил сообщение ПРОМЕЖУТКА и затем "инициировал" следующее с вызовом window.setTimeout с очень малой задержкой (скажите что 10 мс). Это приводит к управлению и позволяет браузеру перекрашивать ПРОМЕЖУТОК с обновленным сообщением прежде, чем запустить следующий шаг.

Однако я нахожу это очень грязным и трудным следовать коду, я думаю, что должен быть лучший путь. У кого-либо есть какие-либо предложения? Там какой-либо путь состоит в том, чтобы вынудить ПРОМЕЖУТОК перекрасить, не имея необходимость оставлять контекст функции?

Спасибо

7
задан LambyPie 7 April 2010 в 12:23
поделиться

6 ответов

То, как вы это делаете, является правильным (на данный момент это может измениться по мере появления и принятия стандартов [см. Эндрю Айлетт ответ ], но пока не скоро). Вы должны уступить так, чтобы браузер мог обновлять пользовательский интерфейс. Я обнаружил, что чем больше я так думаю, тем чище становится, но мои первые несколько попыток сделать это действительно были довольно «беспорядочными». Надеюсь, вы найдете то же самое, когда к этому привыкнете.

7
ответ дан 6 December 2019 в 21:11
поделиться

Не знаю. Вы можете разбить свой код таким образом, чтобы отдельные функции могли совместно использовать переменные, таким образом:

var a = some_local_state();
runTasksWithProgress([
    function() {
        do_some_work(a);
        a = a + 1;
    },
    function() {
        do_some_other_work(a);
        a = a * 2;
    },
    ...
    ]);

runTasksWithProgress немного сложнее. По сути, вы вызываете первую задачу, обновляете статус, а затем настраиваете обратный вызов для выполнения последующих задач.

Этот подход может частично облегчить боль.

0
ответ дан 6 December 2019 в 21:11
поделиться

Это все равно, что спросить, можно ли прервать процедуру, не прерывая ее. Ответ - нет. Вы должны использовать setTimeout () или setInterval (), чтобы передать управление механизму рендеринга браузера.

Если вы используете setInterval (), вы можете запустить этот процесс, а в вашей выполняемой функции просто обновите внешнюю переменную, которая будет опрашиваться функцией, вызываемой setInterval (). Таким образом, вам нужно сделать только один вызов вместо того, чтобы делать их в цикле.

0
ответ дан 6 December 2019 в 21:11
поделиться

Если у вас есть контроль над целевым браузером, вы можете использовать Рабочий поток HTML5 для выполнения работы в фоновом режиме.

3
ответ дан 6 December 2019 в 21:11
поделиться

Вы должны знать, что в некоторых браузерах вы получите сообщение о тайм-ауте скрипта, если у вас есть долго работающий скрипт. Так что на самом деле желательно разделить это с помощью таймера.

Сказав это, если вы ищете действительно структурированный способ сделать это, вы можете посмотреть библиотеку фоновых задач, которую я написал для проекта проверки орфографии. Это позволяет вам реализовать отображение / сокращение для массивов данных по таймеру.

https://github.com/jameswestgate/taskjs

2
ответ дан 6 December 2019 в 21:11
поделиться

Что-то вроде этого может сработать, если ваша функция выполняется в цикле. Он проверяет соответствие количество времени, которое прошло, и обновляет индикатор выполнения, если прошло 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);
0
ответ дан 6 December 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: