Книга: JavaScript. Подробное руководство, 6-е издание

13.3.1. Синхронные, асинхронные и отложенные сценарии

13.3.1. Синхронные, асинхронные и отложенные сценарии

Когда поддержка JavaScript впервые появилась в веб-броузерах, не существовало никаких инструментов обхода и управления структурой содержимого документа. Единственный способ, каким JavaScript-код мог влиять на содержимое документа, - это генерировать содержимое в процессе загрузки документа. Делалось это с помощью метода document.write(). В примере 13.3 показано, как выглядел ультрасовременный JavaScript-код в 1996 году.

Пример 13.3. Генерация содержимого документа во время загрузки

<h1>Таблица факториалов</h1>
<script>
  function factorial(n) { // Функция вычисления факториалов
    if (п <= 1) return п;
    else return n*factorial(n-1);
  }
  document.write("<table>"); // Начало HTML-таблицы
  document.write("<tr><th>n</thxth>n!</th></tr>"); // Вывести заголовок таблицы
  for(var і = 1; і <= 10; і++) { // Вывести 10 строк
    document. write("<trxtd>" + і + "</tdxtd>" + factorial(i) + "</td></tr>");
  }
  document.write("</table>”); // Конец таблицы
  document.write("Generated at " + new Date()); // Вывести время
</script>

Когда сценарий передает текст методу document.write(), этот текст добавляется во входной поток документа, и механизм синтаксического анализа разметки HTML действует так, как если бы элемент <script> был замещен этим текстом. Использование метода document.write() более не считается хорошим стилем программирования, но его применение по-прежнему возможно (раздел 15.10.2), и этот факт имеет важное следствие. Когда механизм синтаксического анализа разметки HTML встречает элемент <script>, он должен, по умолчанию, выполнить сценарий, прежде чем продолжить разбор и отображение документа. Это не является проблемой для встроенных сценариев, но если сценарий находится во внешнем файле, на который ссылается атрибут src, это означает, что часть документа, следующая за сценарием, не появится в окне броузера, пока сценарий не будет загружен и выполнен.

Такой синхронный, или блокирующий, порядок выполнения действует только по умолчанию. Тег <script> может иметь атрибуты defer и async, которые (в броузерах, поддерживающих их) определяют иной порядок выполнения сценариев. Это логические атрибуты - они не имеют значения; они просто должны присутствовать в теге <script>. Согласно спецификации HTML5, эти атрибуты принимаются во внимание, только когда используются вместе с атрибутомsrc, однако некоторые броузеры могут поддерживать атрибут defer и для встроенных сценариев:

<script defer src="deferred.js"></script>
<script async src="async.js"></script>

Оба атрибута, defer и async, сообщают броузеру, что данный сценарий не использует метод document.write() и не генерирует содержимое документа, и что броузер может продолжать разбор и отображение документа, пока сценарий загружается. Атрибут defer заставляет броузер отложить выполнение сценария до момента, когда документ будет загружен, проанализирован и станет готов к выполнению операций. Атрибут async заставляет броузер выполнить сценарий, как только это станет возможно, но не блокирует разбор документа на время загрузки сценария. Если тег <script> имеет оба атрибута, броузер, поддерживающий оба этих атрибута, отдаст предпочтение атрибуту async и проигнорирует атрибут defer.

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

На момент написания этих строк атрибуты async и defer поддерживались не всеми броузерами, поэтому их следует рассматривать лишь как подсказки для оптимизации: веб-страницы должны проектироваться так, чтобы они продолжали корректно работать, даже если отложенные и асинхронные сценарии выполняются броузером синхронно.

Имеется возможность загружать и выполнять сценарии асинхронно, даже если броузер не поддерживает атрибут async, для чего достаточно динамически создать элемент <script> и вставить его в документ. Это действие реализует функция loadasync(), представленная в примере 13.4. Используемые ею приемы описываются в главе 15.

Пример 13.4. Асинхронная загрузка и выполнение сценария

// Асинхронная загрузка сценария из указанного URL-адреса и его выполнение
function loadasync(url) {
  var head = document.getElementsByTagName("head")[0]; // Отыскать <head>
  var s = document.createElement("script"); // Создать элемент <script>
  s.src = url; // Установить атрибут src
  head.appendChild(s); // Вставить <script> в <head>
}

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

Оглавление книги


Генерация: 0.052. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз