Require.js (almond.js) Отключение по времени

Я пытаюсь использовать Almond.js и оптимизатор Require.js для создания отдельного файла, который можно использовать без Require.js. Мне удалось успешно скомпилировать файл, и весь код работает, но есть одна проблема: код выполняется в неправильном порядке.

Допустим, мой основной файл (тот, что в параметре include=, переданном оптимизатору) имеет следующее:

console.log('outside');
require(['someFile'], function(someModule) {
    console.log('inside');
    window.foo = someModule.rightValue;
});

а затем в моем HTML у меня есть:

<script src="myCompiledFile.js"></script>
<script>
    console.log('out in the HTML');
</script>

Поскольку я использую almond.js и скомпилированный файл (и, следовательно, загрузка файла не происходит), я ожидаю получить результат:

outside
inside
out in the HTML

Однако оказывается, что все еще имеет место некоторая асинхронность, потому что на самом деле я вижу следующее:

outside
out in the HTML
inside

и если я попытаюсь проверить window.foo из HTML, его там нет.

Итак, мой вопрос: как я могу сделать код более похожим на обычный/синхронный файл JS, который сначала запускает весь свой код, прежде чем передать что-то в следующий блок script? Я не могу точно сказать своим пользователям «обернуть весь ваш код в window.setTimeout».


person machineghost    schedule 05.03.2014    source источник


Ответы (1)


По умолчанию Almond повторяет семантику синхронизации вызова require RequireJS. Поскольку require является асинхронным в RequireJS, он также является асинхронным в Almond. Это можно легко увидеть в исходнике: Almond использует setTimeout чтобы запланировать выполнение модуля, даже если он может выполнить его сразу. Это имеет смысл, потому что в общем случае разработчики не ожидают, что код, который они создали для асинхронной работы, вдруг станет синхронным только потому, что они используют Almond. Это не имеет значения в каждом проекте, но в проекте, где пользовательский интерфейс (например) должен обновляться в определенном порядке, изменение семантики синхронизации может привести к поломке кода.

Два варианта:

  • Как говорится в комментарии непосредственно перед setTimeout, использование require('id') работает глобально с Almond. Это связано с тем, что после загрузки вашего пакета все гарантированно будет загружено (поскольку Almond не загружается динамически).

  • Также есть способ вызвать require с дополнительными аргументами. Если четвертый аргумент верен, вызов будет синхронным:

    require(['someFile'], function(someModule) {
        console.log('inside');
        window.foo = someModule.rightValue;
    }, undefined, true);
    

В этом можно убедиться, прочитав код Миндаля. Я не смог найти никакой документации по forceSync (это имя рассматриваемого параметра), но некоторые отчеты об ошибках упомяните об этом, и я не видел там ни одного комментария о том, что это должна быть приватная функциональность.

person Louis    schedule 05.03.2014
comment
Спасибо за всю эту прекрасную информацию, но на самом деле это не решает мою проблему. Неужели невозможно создать общедоступную библиотеку с помощью Require.js? Я действительно не хочу просить всех, кто использует библиотеку, делать require('myLibrary'), я хочу, чтобы они просто могли ссылаться на глобальную переменную (так же, как JQuery, Backbone, Underscore, Require и т. д.). - person machineghost; 05.03.2014
comment
То, что вы спрашиваете в своем комментарии, больше, чем то, что вы задали в своем вопросе. Во всяком случае, отвечено здесь. Вы заметите, что в конце фрагмента используется метод require('id'), который я упомянул в своем ответе как возможное решение. - person Louis; 05.03.2014
comment
Ах, я думал, что мне нужна синхронность для экспорта, но предоставленная вами ссылка кажется идеальным решением. Спасибо. - person machineghost; 05.03.2014
comment
Просто для тех, кто читает это позже, вариант переноса помог, но он все еще не решил основную проблему. Даже если вы используете код по ссылке, предоставленной @Louis, результирующий код, сгенерированный оптимизатором, по-прежнему имеет setTimeout, что означает, что вы все равно не можете использовать свою библиотеку сразу после ее добавления на страницу. - person machineghost; 07.03.2014
comment
@machineghost Неверно, см. здесь. - person Louis; 07.03.2014