MyFunction () против window.setTimeout ('MyFunction ()', 0)? - PullRequest
13 голосов
/ 01 сентября 2009

В javascript, есть ли разница между этими двумя:

// call MyFunction normal way 

MyFunction();

// call MyFunction with setTimeout to 0 //

window.setTimeout('MyFunction()', 0);

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

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

Ответы [ 3 ]

17 голосов
/ 01 сентября 2009

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

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

Ради полноты MyFunction () немедленно выполнит функцию. Очередь не будет задействована.

PS : У Джона Ресига есть несколько полезных заметок о том, как работает механизм синхронизации JavaScript .

PPS : Причина, по которой ваш код "работает" только при использовании setTimeout (fn (), 0), заключается в том, что браузеры могут обновлять DOM только после завершения текущего стека вызовов. Поэтому следующий блок JavaScript будет распознавать изменения DOM, что вполне возможно в вашем случае. Обратный вызов setTimeout () всегда создает новый стек вызовов.

3 голосов
/ 01 сентября 2009

Я бы предположил, что тайм-аут начинается только тогда, когда страница полностью загружена, тогда как простая «MyFunction ()» будет выполняться сразу после ее обработки.

0 голосов
/ 01 сентября 2009

Таймер попытается выполнить, как только ваш текущий поток будет завершен. Это зависит от того, где вы вызываете window.setTimeout (). Если он находится в теге javascript, но не внутри функции, он будет вызван после достижения конца тега javascript. Например:

<html>
<script type="text/javascript">
setTimeout(function(){alert("hello")},0);
var d=Number(new Date())+1000;
while(Number(new Date())<d){

}
alert("hi");
</script>
</html>

Если вы вызываете setTimeout внутри функции, которая возникает в результате события, например, при загрузке, тогда он будет ждать, пока не вернется функция обработчика события:

<html>
<script type="text/javascript">
document.addEventListener("mousedown",function(){
    setTimeout(function(){alert("hello")},0);
    var d=Number(new Date())+1000;
    while(Number(new Date())<d){

    }
    alert("hi");
}, true);
</script>
</html>

Невозможно заставить один поток в JavaScript ждать, пока работает другой поток. Слушатели событий будут ждать, пока текущий поток не будет завершен, прежде чем они начнут работать.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...