Доступ к объекту `goog.require`d в библиотеке закрытия без компиляции

Я экспериментирую с библиотекой Google Closure и прорабатываю официальное руководство по XhrIo. Я столкнулся с некоторыми проблемами с xhr-quick2.js Пример, воспроизведенный ниже:

goog.require('goog.net.XhrIo');

var xhr = new goog.net.XhrIo();

goog.events.listen(xhr, goog.net.EventType.COMPLETE, function(e) {
  obj = this.getResponseJson();
  log('Received Json data object with title property of "' +  
      obj['title'] + '"'); 
  alert(obj['content']);
});

function getData(dataUrl) {
  log('Sending simple request for ['+ dataUrl + ']');
  xhr.send(dataUrl);
}

При запуске я получаю сообщение об ошибке:

Uncaught TypeError: Невозможно прочитать свойство 'XhrIo' из неопределенного

Если я переместить слушатель события и экземпляр XHR в пределах getData функция (которая вызывается в организме onload), все хорошо.

goog.require('goog.net.XhrIo')

function getData(dataUrl) {
  var xhr = new goog.net.XhrIo()

  goog.events.listen(xhr, goog.net.EventType.COMPLETE, function(e) {
    obj = this.getResponseJson()
    log(`Received Json data object with title property of "${ obj["title"] }"`)
    alert(obj["content"])
  })

  log(`Sending simple request for [${ dataUrl }]`)
  xhr.send(dataUrl)
}

function log(msg) {
  document.getElementById('log').appendChild(document.createTextNode(msg));
  document.getElementById('log').appendChild(document.createElement('br'));
}

Я предполагаю, что это потому, что goog.require не закончил импорт net когда goog.net.XhrIo создается в строке 3 первого примера кода. Я полагаю, что идеальным решением является запуск всего моего кода через компилятор замыкания, но я просто экспериментирую, и другие части документации предполагают, что мой рабочий процесс приемлем для разработки.

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

2 ответа

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

Закрытие работает путем сканирования ваших файлов JavaScript для goog.module а также goog.require написать deps.js файл. Этот файл должен быть загружен в первую очередь перед вашими файлами JavaScript. Он перечисляет все модули, используемые кодом, и загружает их в правильном порядке.

Если deps.js приходит первым, потом goog.net будет загружен в тот момент, когда он попадет в ваш код. Код goog.require('goog.net.XhrIo') в строке 1 будет игнорироваться.

Согласно документам goog.require вставит <script> тег после текущего <script> выполняется Так что если вы хотите пропустить шаг использования deps.js тогда вам придется обернуть все в документ, готовый к обратному вызову, или добавить вручную goog.require в файл JavaScript, который загружается перед вашим кодом.

Я думаю, что это не стоит усилий и проще просто использовать средство записи зависимостей замыкания для создания deps.js файл.

Здесь есть краткое руководство:

https://www.safaribooksonline.com/library/view/closure-the-definitive/9781449381882/ch01.html

Вот CLI для написания deps.js файл:

python ../closure-library/closure/bin/calcdeps.py \
    --dep ../closure-library \
    --path my_stuff.js \
    --output_mode deps > deps.js

Для некомпилированного режима требуемый документ должен быть предварительно загружен. Таким образом, в вашем HTML-документе вы должны иметь:

<!DOCTYPE html>
<html>
  <head>
    <script src="path/to/closure/base.js"></script>
    <script>
      goog.require('goog.net.XhrIo');
    </script>
    <script src="mysource.js"></script>
  </head>
</html>

Любые зависимости должны быть загружены в отдельный тег скрипта. Тогда ваши примеры кода выше должны работать.

Другие вопросы по тегам