Загрузка зависимостей модуля ES6 до и после простого скрипта JS - PullRequest
2 голосов
/ 10 мая 2019

У меня есть простой JS-скрипт, parser.js (сгенерированный из инструмента), который зависит от переменных, определенных в модуле ES6, lexer.js. В моем модуле ES6 я уже экспортировал переменные в объект window, поэтому они доступны из parser.js. Однако мне нужно как-то запустить этот модуль ES6 перед запуском скрипта. И, кажется, нет никакого способа сделать это.

Попытка 1: попробуйте загрузить модуль ES6 синхронно, прежде чем включать мой сценарий

Я попробовал нечто подобное в своем HTML.

    <script src="lexer.js" type="module"></script>
    <script src="parser.js"></script>

Но, похоже, он не работает по порядку. lexer.js работает после parser.js

Попытка 2: попытаться синхронно загрузить скрипт внутри модуля ES6

Я попытался создать модуль-обертку ES6 вокруг моего скрипта парсера, вот так

// use import to run the module and load variables into the window
import { lexer } from './lexer.js';

// load parser script synchronously
var req = new XMLHttpRequest();
req.open('GET', 'parser.js', false);
req.send(null);
eval(req.responseText);

Однако, похоже, что синхронные запросы XMLHttpRerec устарели и больше не работают (отредактируйте: на самом деле они работают, см. мой ответ ниже), и я не могу найти какой-либо другой способ синхронной загрузки скрипт. В целом, я бы сказал, что несовместимость между модульной системой ES6 и старой включающей системой javascript не вызывает разочарования.

P.S. Для справки я использую инструмент генерации кода компилятор грамматики Nearley , который позволяет мне ссылаться на мой лексер из грамматики и генерирует простой анализатор JS.

РЕДАКТИРОВАТЬ: @ yong-quan предложил аккуратное решение, просто вставив defer в скрипт включения тега, например,

    <script src="lexer.js" type="module"></script>
    <script src="parser.js" defer></script>

Похоже, это просто откладывает выполнение parser.js до конца. Однако я не упомянул, что на самом деле у меня есть модуль ES6 с именем interpreter.js, который должен вызываться после parser.js. Извините за то, что не упомянул, что раньше, я предположил, что любое решение, работающее для моей первой проблемы, решит и мою вторую проблему. Я исправил заголовок, чтобы уточнить, что мне нужны модули ES6 для запуска до и после моего простого JS-скрипта. По сути, мне нужно интегрировать этот простой JS-скрипт в мой график зависимостей модуля.

РЕДАКТИРОВАТЬ2: Я был не прав, отложенное решение работает. Смотрите @Aviad или мой собственный ответ ниже

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Я думаю, что хорошей практикой здесь будет создание какого-то менеджера загрузок для этого (например, с помощью загрузки чанка веб-пакета / динамического импорта)

Другой вариант - использовать defer атрибуты. Обратите внимание, что defer указывает, что сценарии запускаются в том порядке, в котором они встречались , поэтому вы можете предположить, что parser.js загружается при вызове interpreter.js, если порядок правильный.

Ссылки:

0 голосов
/ 10 мая 2019

Таким образом, я решил проблему, используя решение @ Aviad (опубликовано выше), и добавил defer ко всем моим сценариям, например, так:

    <script src="lexer.js" type="module" defer></script>
    <script src="parser.js" defer></script>
    <script src="interpreter.js" type="module" defer></script>

, и он начал загружатьсяих в правильном порядке.Ухоженная!Хотя я думаю, что важно отметить, что я не нашел фактической спецификации для порядка загрузки модулей ES6, поэтому кажется, что нет никакой гарантии для порядка загрузки (кроме случая, когда один модуль зависит от другого, вкоторый будет загружать зависимости в первую очередь).Итак, пока уловка defer работает, я думаю, что в будущем она может сломаться.

Я также хотел бы отметить, что, оказывается, моя синхронная загрузка скриптов XMLHttpRequest действительно работала,Я просто столкнулся с некоторыми проблемами.Мне пришлось вызвать eval из области действия window, потому что обычно parser.js загружается как тег <script> в HTML, поэтому он ожидает, что область действия будет window, поэтому мне нужно было eval()чтобы подражать, вот так:

// load parser script synchronously
var req = new XMLHttpRequest();
req.open('GET', 'parser.js', false);
req.send(null);
eval.call(window, req.responseText);

Так что я думаю, у меня есть запасной вариант, если мне это нужно.Я также рассматривал возможность ручного преобразования parser.js в модуль ES6, но это избавляет меня от необходимости преобразовывать его каждый раз, когда я его заново генерирую.Спасибо @Aviad за ваше решение!

...