Основное сообщение о загрузке Javascript во время завершения обработки js

Я уверен, что об этом уже спрашивали 1000 раз, в основном все, что я хочу сделать, это изменить содержимое элемента страницы, чтобы отобразить сообщение о загрузке, в то время как мой другой код javascript (довольно ресурсоемкий) завершается. Проблема в том, что сообщение не отображается до тех пор, пока не завершится «другая обработка JS», что полностью противоречит его цели. упрощенный пример...

<html>
<head>
    <title> crappity crapness </title>
    <script type="text/javascript">
        function showMessage(){
            document.getElementById("content").innerHTML = "please wait while we waste some time";
        }

        function wasteTime(){
            //alert("oh joy");
            pausecomp(3000);
            //alert("marvelous!");
        }

        function pausecomp(millis) 
        {
            var date = new Date();
            var curDate = null;

            do { curDate = new Date(); } 
            while(curDate-date < millis);
        } 

    </script>
</head>
<body>
    <div id="content">Blah</div>
    <br/>
    <a href="http://www.google.com" onclick="showMessage(); wasteTime();"> link </a>
</body>

if I uncomment the "oh Joy" alert, the text in the div gets updated Immediatly. how do I make it work without the alert?

Я знаю, что, должно быть, упускаю что-то простое. Спасибо


person hendinas    schedule 31.03.2011    source источник


Ответы (3)


Похоже, вы сталкиваетесь с тем фактом, что Javascript является однопоточным, а браузеры - нет.

По сути, вы не можете одновременно запускать несколько частей Javascript. Однако браузер по-прежнему должен делать что-то помимо выполнения Javascript и продолжает делать это, когда может. Проблема в том, что не определено, является ли изменение DOM синхронным (т. е. выполнение JS останавливается до тех пор, пока оно не будет выполнено) или асинхронным (выполнение JS продолжается). Большинство браузеров делают последнее. Но выполнение JS по-прежнему имеет довольно высокий приоритет, и многие обновления DOM откладываются до тех пор, пока выполнение JS не будет остановлено и подождет. Окно предупреждения является отличным примером, поскольку оно ожидает ввода данных пользователем.

Способ сделать то, что вы хотите сделать, - это воспользоваться преимуществом setTimeout(), которое позволяет завершить текущий фрагмент JS, затем браузер может завершить обновление DOM, а затем он может выполнить JS, ожидающий запуска по тайм-ауту.

person staticsan    schedule 31.03.2011
comment
хорошее объяснение, спасибо за это. Я надеялся сделать это без использования setTimeout (поскольку это была проверка в onSubmit формы), но, похоже, другого пути нет. в любом случае, я думаю, задержка в миллисекунду не так уж и плоха! - person hendinas; 31.03.2011

Было бы неплохо, если бы вы могли асинхронно вызывать функцию showMessage. В других языках вы могли бы сделать это с помощью потоков, а в HTML5 вы можете сделать это с помощью воркеров, которые предназначены именно для таких вещей, но сейчас вы можете просто использовать setTimeout, что делает код в первом аргумент выполняется через определенное время, позволяя текущему коду выполниться раньше, чем он это сделает.

Изменять

   onclick="showMessage(); wasteTime();"

to

   onclick="showMessage; setTimeout(wasteTime,5);"> 
person Peter Olson    schedule 31.03.2011
comment
да, это оно. Я пытался сделать это без setTimeout, но я думаю, это не так уж плохо, если задержка всего на миллисекунду! Спасибо. - person hendinas; 31.03.2011

Ваш pausecomp(3000) по существу блокирует перерисовку браузера из-за цикла while. Вместо этого я бы сделал что-то вроде этого:

function wasteTime(){
    setTimeout(runNext, 3000);
}

function runNext(){
     alert("marvelous!");
}
person Mike Park    schedule 31.03.2011