RequireJS - 无法访问外部模块功能
RequireJS - Cannot Access External Module Function
我遇到了 RequireJS 的问题。本质上,我无法从另一个文件访问另一个文件中定义的函数。
我需要这样做,因为我想导出给定的函数子集,例如
define('submodule', [], function() {
let myFunction1 = function(){ return "Hello"; }
let myFunction2 = function(){ return " From"; }
let myFunction3 = function(){ return " Submodule!"; }
return {
myFunction1 : myFunction1,
myFunction2 : myFunction2,
myFunction3 : myFunction3,
};
});
并从另一个文件访问它们
define('main', ['config', 'sub1', 'sub2', 'submodule'],
function(config, sub1, sub2, submodule) {
//Config
alert(config.conf);
//Submodule
let callSubmodule = function() {
alert(submodule.myFunction1() +
submodule.myFunction2() +
submodule.myFunction3());
}
//sub1
let callSub1 = function() {
alert(sub1.myFunction1());
}
//sub2
let callSub2 = function() {
alert(sub2.myFunction1());
}
});
The fact is that usually I'm able to do this with sub1 and
sub2, but, with submodule, I simply can't. I think it's somehow caused by the dependencies in require.config.js.
我的require.config.js:
require(['common'], function () { //contains vendors
require(['config'], function () { //contains a js config file
require(['main'], function () { //main file
require(['sub1', 'sub2'], function () { //some subfiles
require(['submodule']);
});
});
});
});
对于 submodule.myFunction1() 和我得到的其他两个相关函数:
Uncaught (in promise) TypeError: Cannot read property 'myFunction1' of undefined
这很奇怪,因为我在其他情况下也能做到这一点,但我真的不明白为什么会这样。例如,我可以从主文件和其他文件调用 sub1 和 sub2 函数,但不能调用 submodule 特别是
Index.html
//Taken from Plunker
. . .
<script data-main="common" data-require="require.js@2.1.20" data-semver="2.1.20" src="http://requirejs.org/docs/release/2.1.20/minified/require.js"></script>
<script src="require.config.js"></script>
. . .
<button onclick = "callSubmodule()">Call Submodule</button>
<button onclick = "callSub1()">Call Sub1</button>
<button onclick = "callSub2()">Call Sub2</button>
common.js包含供应商,这里只是一个例子
requirejs.config({
baseUrl : "",
paths : {
"jquery" : "http://code.jquery.com/jquery-latest.min.js"
}
});
sub1.js
define('sub1', ['submodule'], function(submodule) {
let myFunction1 = function(){ return "called sub1"; }
return {
myFunction1 : myFunction1
};
});
sub2.js
define('sub2', ['submodule'], function(submodule) {
let myFunction1 = function(){ return "called sub2"; }
return {
myFunction1 : myFunction1
};
});
我设置了一个 Plunker with @SergGr help 试图复制应用程序的结构,但所有模块在单击时都未定义。在实际应用中,这不会发生。
我该如何解决?
这是您的代码:
define('main', ['submodule'], function(submod) {
console.log(submodule.myFunction());
});
您的参数列表中有 submod
。但是您随后尝试访问 submodule
。请注意,您 return 函数直接来自您的模块 (return myFunction
),因此您的模块具有函数 myFunction
的值,因此您应该调用该模块。代码应该是:
define('main', ['submodule'], function(submod) {
console.log(submod());
});
更新(2017 年 3 月 2 日)
你的 plunker 显然不会工作,因为你有从 HTML 直接调用你的模块函数。
<button onclick = "callSubmodule()">Call Submodule</button>
<button onclick = "callSub1()">Call Sub1</button>
<button onclick = "callSub2()">Call Sub2</button>
RequireJS 不是那样工作的。 RequireJS 的关键目的之一是提供模块隔离,因此它不能那样工作:想象一下如果几个不同的模块具有函数 callSubmodule
.
据我所知,无法将来自 HTML 的调用绑定回 RequireJS 模块中的代码,它应该是另一种方式:模块绑定到 HTML。如果你解决了这些问题,一切对我来说都很好,正如你在 fork of your plunker.
看到的那样
旧答案
错误在您的 subModule.js
define('submodule', [], function() {
let myFunction = function(){ return "Hello"; }
//return myFunction; // old, wrong
return { myFunction: myFunction };
});
即使你只想 return 1 个函数,你也不应该 return 它原样,你应该将它包装到一个对象中并给它一个明确的名称。
P.S。如果这不是您真正的问题,请向我们提供真实的 Minimal, Complete, and Verifiable example
我设法解决了这个问题。本质上,它是由模块之间的 循环依赖性 引起的。所以,a 需要 b 和 b 需要 a 领先其中之一在依赖项解析中未定义。
我在@jgillich 在 requirejs module is undefined 提供的答案中找到了解决方案。
所以,我设法解决了在 main
中使用
define('main', ['config', 'sub1', 'sub2', 'require'],
function(config, sub1, sub2, submodule, require) {
//Config
alert(config.conf);
//Submodule
let callSubmodule = function() {
alert(require('submodule').myFunction1() +
require('submodule').myFunction2() +
require('submodule').myFunction3());
}
});
正如@jgillich 所说:
If you define a circular dependency ("a" needs "b" and "b" needs "a"), then in this case when "b"'s module function is called, it will get an undefined value for "a". "b" can fetch "a" later after modules have been defined by using the require() method (be sure to specify require as a dependency so the right context is used to look up "a"):
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if "a" also asked for "b",
//a circular dependency.
return function(title) {
return require("a").doSomething();
}
}
);
您命名模块的方式我希望它们都来自 require 配置文件。我不希望 requirejs 知道如何在没有某种显式编译过程的情况下加载这些文件。我还怀疑您的服务器由于 404 而返回了一些东西,JS 几乎可以在不爆炸的情况下解释它。
您的设置和命名方案似乎很奇怪。如果您有能力从头开始,下面是我的建议。
建议:
- 我注意到您使用的是绝对路径。我强烈建议对所有内容使用相对路径。这有很多原因。
- 您的主数据应该是您所说的"require.config.js"。你的 common.js 实际上是一个 require.config.js。
- 您使用脚本标签单独加载 require.config.js(这是您的主程序)。你可以这样做,但这很奇怪。
- 您可以使用 "commonjs" 样式语法来获取文件,而无需使用数组来定义所有依赖项。我推荐。
这是我的设置建议:
index.html
<script src="/js/config.js" />
<script src="http://requirejs.org/docs/release/2.1.20/minified/require.js" />
<script>
require('/js/main', function(main) {
main({});
});
</script>
/js/config.js
// setting requirejs to an object before its loaded will cause requirejs to use it as the config
window.requirejs = {
baseUrl : "/",
paths : {
"jquery" : "http://code.jquery.com/jquery-latest.min.js"
}
};
/js/main.js
define(function(require) {
const sum = require('./sum');
return (a, b) => sum(a, b);
});
/js/sum.js
define(function(require) {
return (a, b) => a + b;
});
我遇到了 RequireJS 的问题。本质上,我无法从另一个文件访问另一个文件中定义的函数。
我需要这样做,因为我想导出给定的函数子集,例如
define('submodule', [], function() {
let myFunction1 = function(){ return "Hello"; }
let myFunction2 = function(){ return " From"; }
let myFunction3 = function(){ return " Submodule!"; }
return {
myFunction1 : myFunction1,
myFunction2 : myFunction2,
myFunction3 : myFunction3,
};
});
并从另一个文件访问它们
define('main', ['config', 'sub1', 'sub2', 'submodule'],
function(config, sub1, sub2, submodule) {
//Config
alert(config.conf);
//Submodule
let callSubmodule = function() {
alert(submodule.myFunction1() +
submodule.myFunction2() +
submodule.myFunction3());
}
//sub1
let callSub1 = function() {
alert(sub1.myFunction1());
}
//sub2
let callSub2 = function() {
alert(sub2.myFunction1());
}
});
The fact is that usually I'm able to do this with sub1 and sub2, but, with submodule, I simply can't. I think it's somehow caused by the dependencies in require.config.js.
我的require.config.js:
require(['common'], function () { //contains vendors
require(['config'], function () { //contains a js config file
require(['main'], function () { //main file
require(['sub1', 'sub2'], function () { //some subfiles
require(['submodule']);
});
});
});
});
对于 submodule.myFunction1() 和我得到的其他两个相关函数:
Uncaught (in promise) TypeError: Cannot read property 'myFunction1' of undefined
这很奇怪,因为我在其他情况下也能做到这一点,但我真的不明白为什么会这样。例如,我可以从主文件和其他文件调用 sub1 和 sub2 函数,但不能调用 submodule 特别是
Index.html
//Taken from Plunker
. . .
<script data-main="common" data-require="require.js@2.1.20" data-semver="2.1.20" src="http://requirejs.org/docs/release/2.1.20/minified/require.js"></script>
<script src="require.config.js"></script>
. . .
<button onclick = "callSubmodule()">Call Submodule</button>
<button onclick = "callSub1()">Call Sub1</button>
<button onclick = "callSub2()">Call Sub2</button>
common.js包含供应商,这里只是一个例子
requirejs.config({
baseUrl : "",
paths : {
"jquery" : "http://code.jquery.com/jquery-latest.min.js"
}
});
sub1.js
define('sub1', ['submodule'], function(submodule) {
let myFunction1 = function(){ return "called sub1"; }
return {
myFunction1 : myFunction1
};
});
sub2.js
define('sub2', ['submodule'], function(submodule) {
let myFunction1 = function(){ return "called sub2"; }
return {
myFunction1 : myFunction1
};
});
我设置了一个 Plunker with @SergGr help 试图复制应用程序的结构,但所有模块在单击时都未定义。在实际应用中,这不会发生。
我该如何解决?
这是您的代码:
define('main', ['submodule'], function(submod) {
console.log(submodule.myFunction());
});
您的参数列表中有 submod
。但是您随后尝试访问 submodule
。请注意,您 return 函数直接来自您的模块 (return myFunction
),因此您的模块具有函数 myFunction
的值,因此您应该调用该模块。代码应该是:
define('main', ['submodule'], function(submod) {
console.log(submod());
});
更新(2017 年 3 月 2 日)
你的 plunker 显然不会工作,因为你有从 HTML 直接调用你的模块函数。
<button onclick = "callSubmodule()">Call Submodule</button>
<button onclick = "callSub1()">Call Sub1</button>
<button onclick = "callSub2()">Call Sub2</button>
RequireJS 不是那样工作的。 RequireJS 的关键目的之一是提供模块隔离,因此它不能那样工作:想象一下如果几个不同的模块具有函数 callSubmodule
.
据我所知,无法将来自 HTML 的调用绑定回 RequireJS 模块中的代码,它应该是另一种方式:模块绑定到 HTML。如果你解决了这些问题,一切对我来说都很好,正如你在 fork of your plunker.
看到的那样旧答案
错误在您的 subModule.js
define('submodule', [], function() {
let myFunction = function(){ return "Hello"; }
//return myFunction; // old, wrong
return { myFunction: myFunction };
});
即使你只想 return 1 个函数,你也不应该 return 它原样,你应该将它包装到一个对象中并给它一个明确的名称。
P.S。如果这不是您真正的问题,请向我们提供真实的 Minimal, Complete, and Verifiable example
我设法解决了这个问题。本质上,它是由模块之间的 循环依赖性 引起的。所以,a 需要 b 和 b 需要 a 领先其中之一在依赖项解析中未定义。
我在@jgillich 在 requirejs module is undefined 提供的答案中找到了解决方案。
所以,我设法解决了在 main
中使用define('main', ['config', 'sub1', 'sub2', 'require'],
function(config, sub1, sub2, submodule, require) {
//Config
alert(config.conf);
//Submodule
let callSubmodule = function() {
alert(require('submodule').myFunction1() +
require('submodule').myFunction2() +
require('submodule').myFunction3());
}
});
正如@jgillich 所说:
If you define a circular dependency ("a" needs "b" and "b" needs "a"), then in this case when "b"'s module function is called, it will get an undefined value for "a". "b" can fetch "a" later after modules have been defined by using the require() method (be sure to specify require as a dependency so the right context is used to look up "a"):
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if "a" also asked for "b",
//a circular dependency.
return function(title) {
return require("a").doSomething();
}
}
);
您命名模块的方式我希望它们都来自 require 配置文件。我不希望 requirejs 知道如何在没有某种显式编译过程的情况下加载这些文件。我还怀疑您的服务器由于 404 而返回了一些东西,JS 几乎可以在不爆炸的情况下解释它。
您的设置和命名方案似乎很奇怪。如果您有能力从头开始,下面是我的建议。
建议:
- 我注意到您使用的是绝对路径。我强烈建议对所有内容使用相对路径。这有很多原因。
- 您的主数据应该是您所说的"require.config.js"。你的 common.js 实际上是一个 require.config.js。
- 您使用脚本标签单独加载 require.config.js(这是您的主程序)。你可以这样做,但这很奇怪。
- 您可以使用 "commonjs" 样式语法来获取文件,而无需使用数组来定义所有依赖项。我推荐。
这是我的设置建议:
index.html
<script src="/js/config.js" />
<script src="http://requirejs.org/docs/release/2.1.20/minified/require.js" />
<script>
require('/js/main', function(main) {
main({});
});
</script>
/js/config.js
// setting requirejs to an object before its loaded will cause requirejs to use it as the config
window.requirejs = {
baseUrl : "/",
paths : {
"jquery" : "http://code.jquery.com/jquery-latest.min.js"
}
};
/js/main.js
define(function(require) {
const sum = require('./sum');
return (a, b) => sum(a, b);
});
/js/sum.js
define(function(require) {
return (a, b) => a + b;
});