开发者问题收集

RequireJS-无法访问外部模块功能

2017-02-23
1697

我遇到了 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="[email protected]" 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
    };

});

我在@SergGr 的帮助下设置了一个 Plunker ,它试图复制应用程序的结构,但点击时所有模块都未定义。在实际应用中,这种情况不会发生。

我该如何解决这个问题?

3个回答

这是您的代码:

define('main', ['submodule'], function(submod) {
   console.log(submodule.myFunction());
});

参数列表中有 submod 。但您随后尝试访问 submodule 。请注意,您直接从模块返回函数( return myFunction ),因此您的模块具有函数 myFunction 的值,因此您应该调用该模块。代码应为:

define('main', ['submodule'], function(submod) {
   console.log(submod());
});
Louis
2017-02-23

我设法解决了这个问题。本质上,这是由模块之间的 循环依赖 引起的。因此, a 需要 b 并且 b 需要 a ,导致其中一个在依赖项解析中未定义。

我在 @jgillich 在 requirejs 模块未定义 提供的答案中找到了解决方案。

因此,我设法在 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();
        }
    }
);

http://requirejs.org/docs/api.html#circular

AndreaM16
2017-03-03

根据您命名模块的方式,我认为它们都来自一个 require 配置文件。我并不认为 requirejs 知道如何在不经过某种显式编译过程的情况下加载这些文件。我还怀疑您的服务器由于 404 而返回了某些内容,而 JS 几乎能够解释该内容而不会崩溃。

您的设置和命名方案似乎很奇怪。如果您有能力从头开始,以下是我的建议。

建议:

  • 我注意到您使用的是绝对路径。我强烈建议对所有内容使用相对路径。这样做的原因有很多。
  • 您的 data-main 应该是您所说的“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;
});
Parris
2017-03-04