Подтвердить что ты не робот

Может ли прерывание работы JavaScript прерываться?

Я всегда думал, что, поскольку JavaScript был однопоточным, я мог присоединять обработчики событий, не беспокоясь о том, что обработчики выполняются, пока я был в середине выполнения кода. К моему удивлению, я обнаружил, что они могут. Согласно этот ответ, диалоговое окно "Невосприимчивое Script" может вызвать события, которые должны быть подняты, пока script все еще работает.

Я проверил это со следующим кодом:

<script>
    function loop() {
        var cond;
        onblur = function (event) {
            cond = false;
        };
        cond = true;
        while (cond)
            ;
        alert('loop exited!');
    }
</script>
<button onclick="loop()">loop()</button>

(jsFiddle)

В Firefox 11.0 функция выводит "loop exited" после нажатия кнопки continue. Кажется, что петля приостановлена, и события разрешены для выполнения. Это похоже на Сигнал Unix, который временно изменяет контекст целевого потока. Но это намного опаснее, так как позволяет изменять внешнее состояние.

Это ошибка? Должна ли я больше не зависеть от модели JavaScript с одним потоком исполнения и гарантировать, что все мои скрипты будут повторно введены? Или это недостаток, которого не стоит преследовать, несмотря на то, что основной браузер позволяет это произойти?

4b9b3361

Ответ 1

Итак, если вы создадите бесконечный цикл, вы повесите свой JavaScript. Diff браузеры будут обрабатывать это по-другому. Firefox 11 для меня подбрасывает окно, в котором отображается ваш script. Chrome сейчас просто работает для меня.

Это должно доказать точку. Никогда не называет alert() в FF11 или Chrome 17.

while(true){}
alert("sucks");

http://jsfiddle.net/JCKRt/1/

Вы спросили о операторах синхронизации в JavaScript. Есть еще несколько синхронных операторов, которые будут блокировать выполнение JavaScript, например alert(), confirm(), синхронные вызовы ajax и многое другое.

Обычно вы хотите избежать каких-либо синхронных вещей в JavaScript! Если вы хотите, чтобы что-то приостановилось, вы можете подумать о дизайне. JavaScript управляется событиями. Вам не нужно, чтобы он вращался в цикле while, потому что ничего на странице будет работать, включая любые события, такие как клики и т.д.

Ответ 2

Я думаю, что проблема возникает, когда вы начинаете заниматься событиями.

Вместо использования цикла while рассмотрите возможность использования рекурсивной функции.

Вот некоторые изменения, которые я сделал для вашего кода, который должен выполняться по желанию.

<head>
    <script>
    function loop(that) {
        var cond;
        that.onblur = function (event) {
            cond = false;
        };
        cond = true;
        var loop = 0
        var xy = function x (){
            if(cond == true){
                loop++;         
                setTimeout(function(){xy()},0);
            } else {
                alert('loop exited! - '+loop);
                return true;
            }
        }
        xy();
    }
    </script>
</head>
<body>
    <button onclick="this.focus(); loop(this)">loop()</button>
</body>

Использование setTimeout() с задержкой 0 должно позволить любым событиям входить без каких-либо проблем. Ваш код цикла не будет выполнен почти так же быстро, но вам просто нужно его протестировать и посмотреть.