javascript RequireJS 中的动态要求,收到“尚未为上下文加载模块名称”错误?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17446844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamic require in RequireJS, getting "Module name has not been loaded yet for context" error?
提问by gremo
Is there a way to define a module that "dynamically" load other modules in RequireJS? If yes, how the optimizer (r.js) understands how/when a module has to be included?
有没有办法在 RequireJS 中定义一个“动态”加载其他模块的模块?如果是,优化器 (r.js) 如何理解如何/何时必须包含模块?
For example, let dynModules
a module which defines name/path pairs:
例如,让dynModules
一个定义名称/路径对的模块:
define([], function () {
return ['moduleA', 'moduleB']; // Array of module names
});
Another module is going to load modules dynamically, based on the array. This will not work:
另一个模块将根据数组动态加载模块。这将不起作用:
define(['dyn_modules'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
... gives me:
... 给我:
Uncaught Error: Module name "moduleA" has not been loaded yet for context: _. Use require([]) http://requirejs.org/docs/errors.html#notloaded
未捕获的错误:尚未为上下文加载模块名称“moduleA”:_。使用 require([]) http://requirejs.org/docs/errors.html#notloaded
I can solve the error, but it's not "dynamic" anymore:
我可以解决错误,但它不再是“动态的”:
define(['dyn_modules', 'moduleA', 'moduleB'], function (dynModules) {
for(name in dynModules) {
var module = require(path); // Call RequireJS require
}
// ...
});
回答by explunit
The limitation relates to the simplified CommonJS syntax vs. the normal callback syntax:
限制与简化的 CommonJS 语法与普通回调语法有关:
- http://requirejs.org/docs/whyamd.html#commonjscompat
- https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define
- http://requirejs.org/docs/whyamd.html#commonjscompat
- https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define
Loading a module is inherently an asynchronous process due to the unknown timing of downloading it. However, RequireJS in emulation of the server-side CommonJS spec tries to give you a simplified syntax. When you do something like this:
由于下载模块的时间未知,加载模块本质上是一个异步过程。但是,模拟服务器端 CommonJS 规范的 RequireJS 试图为您提供简化的语法。当你做这样的事情时:
var foomodule = require('foo');
// do something with fooModule
What's happening behind the scenes is that RequireJS is looking at the body of your function code and parsing out that you need 'foo' and loading it prior to your function execution. However, when a variable or anything other than a simple string, such as your example...
幕后发生的事情是 RequireJS 正在查看您的函数代码的主体并解析出您需要 'foo' 并在您的函数执行之前加载它。但是,当变量或简单字符串以外的任何内容时,例如您的示例...
var module = require(path); // Call RequireJS require
...then Require is unable to parse this out and automatically convert it. The solution is to convert to the callback syntax;
...然后 Require 无法解析它并自动转换它。解决方法是转换为回调语法;
var moduleName = 'foo';
require([moduleName], function(fooModule){
// do something with fooModule
})
Given the above, here is one possible rewrite of your 2nd example to use the standard syntax:
鉴于上述情况,这里是您的第二个示例的一种可能重写以使用标准语法:
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: From your own answer, I see you're using underscore/lodash, so using _.values
and _.object
can simplify the looping through arguments array as above.
编辑:从您自己的答案中,我看到您正在使用下划线/lodash,因此使用_.values
和_.object
可以简化上述参数数组的循环。
回答by gremo
Answering to myself. From the RequireJS website:
回答我自己。从 RequireJS 网站:
//THIS WILL FAIL
define(['require'], function (require) {
var namedModule = require('name');
});
This fails because requirejs needs to be sure to load and execute all dependencies before calling the factory function above. [...] So, either do not pass in the dependency array, or if using the dependency array, list all the dependencies in it.
这失败是因为 requirejs 需要确保在调用上面的工厂函数之前加载并执行所有依赖项。[...] 因此,要么不传入依赖项数组,要么如果使用依赖项数组,则列出其中的所有依赖项。
My solution:
我的解决方案:
// 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'
};
});
The loader:
装载机:
define(['jade', 'lodash', 'config'], function (Jade, _, Config) {
var deps;
// Dynamic require
require(_.values(Config), function () {
deps = _.object(_.keys(Config), arguments);
// Use deps...
});
});