Динамическое требование в RequireJS, получение ошибки" имя модуля еще не загружено для контекста"?
есть ли способ определить модуль, который "динамически" загружает другие модули в RequireJS? Если да, то как оптимизатор (r.js) понимает, как/когда модуль должен быть включен?
например,dynModules модуль, который определяет пары имя/путь:
define([], function () {
return ['moduleA', 'moduleB']; // Array of module names
});
другой модуль будет загружать модули динамически, на основе массива. Это будет не работает:
define(['dyn_modules'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
... дает мне:
Непойманные Ошибка: Модуль наименование "модуль" еще не загружены
контекст._ : Использовать требуется([])
http://requirejs.org/docs/errors.html#notloaded
Я могу решить ошибку, но это уже не" динамический":
define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
2 ответов:
ограничение относится к упрощенному синтаксису CommonJS по сравнению с обычным синтаксисом обратного вызова:
- http://requirejs.org/docs/whyamd.html#commonjscompat
- https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define
загрузка модуля по своей сути является асинхронным процессом из-за неизвестного времени его загрузки. Однако, RequireJS в эмуляция спецификации CommonJS на стороне сервера пытается дать вам упрощенный синтаксис. Когда вы делаете что-то вроде этого:
var foomodule = require('foo'); // do something with fooModuleто, что происходит за кулисами, заключается в том, что RequireJS смотрит на тело вашего кода функции и анализирует, что вам нужно " foo " и загружает его до выполнения функции. Однако, когда переменная или что-то другое, чем простая строка, например, ваш пример...
var module = require(path); // Call RequireJS require...затем Require не может разобрать это и автоматически конвертировать его. Решение заключается в преобразовании синтаксиса обратного вызова;
var moduleName = 'foo'; require([moduleName], function(fooModule){ // do something with fooModule })учитывая вышесказанное, вот один из возможных вариантов переписывания вашего 2-го примера для использования стандартного синтаксиса:
define(['dyn_modules'], function (dynModules) { require(dynModules, function(){ // use arguments since you don't know how many modules you're getting in the callback for (var i = 0; i < arguments.length; i++){ var mymodule = arguments[i]; // do something with mymodule... } }); });EDIT: из вашего собственного ответа я вижу, что вы используете подчеркивание/lodash, поэтому используйте
_.valuesи_.objectможно упростить цикл через массив аргументов, как указано выше.
отвечая самому себе. С сайта RequireJS:
//THIS WILL FAIL define(['require'], function (require) { var namedModule = require('name'); });это не удается, потому что requirejs должен быть уверен, чтобы загрузить и выполнить все зависимости перед вызовом функции фабрики выше. [...] Итак, либо не передавайте массив зависимостей, либо, если вы используете массив зависимостей, перечислите все зависимости в нем.
мое решение:
// Modules configuration (modules that will be used as Jade helpers) define(function () { return { 'moment': 'path/to/moment', 'filesize': 'path/to/filesize', '_': 'path/to/lodash', '_s': 'path/to/underscore.string' }; });загрузчика:
define(['jade', 'lodash', 'config'], function (Jade, _, Config) { var deps; // Dynamic require require(_.values(Config), function () { deps = _.object(_.keys(Config), arguments); // Use deps... }); });
Comments