2015-11-18 2 views
1

Мне показалось, что я понял, как работает метод setTimeout, но это меня сбивает с толку.Не понимаю этого setTimeout в JS

test.html (Я пытаюсь загрузить файл test.js перед файлом jQuery для демонстрации. Скажем, файл jQuery размещен локально).

<body> 
// ...code 
<div id="area"></div> 
// ...code 

<script src="test.js"></script> 
<script src="jquery.js"></script> 
</body> 

test.js

$('#area').text('hello'); 

Я понимаю, в данном случае «привет» не получить напечатанный на браузере, потому что Jquery загружается после файла test.js. Переключение порядка этих файлов решает проблему. Но если оставить в покое заказ, и изменить файл test.js, SetTimeout делает его работу:

function wait() { 
    if(window.jQuery) { 
     $('#area').text("hello"); 
    } 
    else 
    { 
     setTimeout(wait, 10); 
    } 
} 

wait(); 

В этом случае «привет» текст печатается в браузере. Но я как бы почесываю голову, потому что каким-то образом загружается файл jQuery. Но как? Почему файл test.js не попадает в бесконечный цикл навсегда, проверяя, загружен ли jQuery? Я был бы признателен за то, что я знаю о механизме происходящего.

+0

Почему вы думаете, что _would_ пойманы в бесконечном цикле? –

+0

Из-за очереди событий –

+2

Это работает, потому что, когда загружается jQuery, переменная (jQuery) сохраняется в пространстве имен окна. Таким образом, ваш тайм-аут проверяет каждые 10 мс, если jQuery уже сохранен. – ItsGreg

ответ

2

Почему файл test.js не попадает в бесконечный цикл навсегда, проверяя, загружен ли jQuery?

setTimeout работает асинхронно. Он не приостанавливает браузер. Он просто просит его выполнить определенную функцию через определенное количество миллисекунд.

jquery.js загружается и выполняется междуwait() invocations.

+0

Спасибо. Я думал, что задержка _did_ заставляет браузер останавливаться. Другой вопрос, который у меня есть, похоже, что я выполняю функцию ожидания дважды, один раз в методе setTimeout и снова с wait(). Он работает дважды? –

+0

@MatthewMoon эта строка кода: 'setTimeout (wait, 10)' does ** not ** execute 'wait' (обратите внимание, что скобок нет), он просто планирует его выполнить. Первоначально 'wait()' выполняется один раз - в последней строке вашего кода (обратите внимание на круглые скобки). И тогда это будет зависеть от оценки 'if (window.jQuery)' '' 'wait' будет запланировано для запуска снова. Если каким-то образом 'jQuery' уже был загружен в этот момент, то' wait' не будет запускаться во второй раз. –

2

Без этого кода setTimeout(), когда содержимое «test.js» оценивается, браузер сразу же столкнется с проблемой $ (jQuery), которая не определена. СsetTimeout(), однако, код не пытается использовать глобальные символы jQuery, пока он не проверит, что символы определены.

Без кода setTimeout код выходит из строя с ошибкой времени выполнения. Код в другой версии явно проверяет эту возможность отказа, чтобы избежать этого.

4

Там будет быть бесконечным циклом, если jQuery никогда не загружается. Но в обычном случае:

  1. Первый раз через, JQuery не загружен, поэтому мы setTimeout() 1. В то же время происходят другие события, в том числе загрузка таких ресурсов, как jQuery
  2. Через 10 месяцев мы снова проверим.
  3. Загружается ли jQuery сейчас? Если нет, установите тайм-аут и вернитесь к шагу 2
  4. После некоторого количества попыток, jQuery делает load, и мы выключены.

Лучший способ сделать все это, конечно, было бы

  1. нагрузки JQuery первый
  2. Запустите wait() функцию в ready() обработчика, так что не работает, пока он не нужен ,
<script src="jquery.js"></script> 
<script src="test.js"></script> 
// test.js 
$(document).ready( 
    function() 
    { 
    $('#area').text("hello"); 
    } 
); 
+0

Это хорошее объяснение. –

0

JavaScript предварительно не скомпилирован. Он работает «на лету».

Вы можете добавить код «на лету», когда захотите, и это включает загрузку целостных библиотек. Как только браузер загрузит внешний JS-файл, он анализирует его, и все готово к использованию.

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

1

setTimeOut метод запускается в отдельной очереди, называемой асинхронным обратным вызовом. поэтому, как только интерпретатор приходит к этой строке, код перемещается в отдельную очередь и продолжает его синтаксический анализ (который затем выполняет jQuery.js). После этого он ищет элементы асинхронной очереди, чтобы проверить, завершен ли тайм-аут, а затем выполняется метод внутри setTimeout. К этому времени jQuery.js уже загружен.

Подробнее об этом https://youtu.be/8aGhZQkoFbQ

+0

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

Смежные вопросы