定义命名模块并同时要求它

时间:2014-02-11 14:56:39

标签: requirejs

在我的应用程序中,我希望以编程方式创建命名模块,并在使用define访问它时。以简化形式,它看起来如下:

define("myModule", [], function() {
    return {
        myModule: true
    };
});
var obj = require('myModule');

虽然我没有看到任何问题,为什么它不能以这种方式工作,require.js当然会这样说:

MODULE NAME ... HAS NOT BEEN LOADED YET FOR CONTEXT: ...

如果我按照以下方式更改我的代码,它会起作用:

define("myModule", [], function() {
    return {
        myModule: true
    };
});
require(['myModule'], function(obj){

});

但是现在它是异步代码,我不希望这样。

1 个答案:

答案 0 :(得分:1)

看起来同步的require形式实际上只是sugar,允许以类似于CommonJS的方式编写代码,并帮助将CommonJS代码移植到RequireJS。不幸的是,它生成的错误消息未正确指出问题的性质。这种形式的require工作正常,只要模块已经已定义已初始化,就会返回一个模块。如果尚未定义和初始化,则失败。由于这种require形式不初始化模块,因此必须使用异步表单来初始化它们。

我认为这不会改变。截至去年7月,James Burke(RequireJS的首席开发人员)表示支持同步动态加载脚本有no plans

我可以通过两种方式看到这个:

  1. 将整个应用程序包装在一个异步require调用中,该调用将加载您要使用的所有模块var foo = require('foo');。我知道您提到过要避免异步调用,但是您没有指定您想要避免的是在整个应用中是否有异步require调用传播。我在这里建议的是启动应用程序的一个异步require调用:

    require(['main', 'myModule', ... other modules ...], function (main) {
        main();
    });
    

    假设main模块是应用程序的主要入口点,那么您可以在应用程序代码的任何位置执行var myModule = require('myModule');因为myModule已经定义并且在执行同步require之前初始化

  2. 为RequireJS创建并行系统。这样的事情有效:

      var syncmap = Object.create(null);
      function syncdefine(name, factory) {
          var mod = factory();
          syncmap[name] = mod;
          define(name, mod);
      }
    
      function syncrequire(name) {
          return syncmap[name];
      }
    
      syncdefine("myModule", function () {
          return {
              myModule: true
          };
      });
    
      console.log("outside", syncrequire("myModule").myModule);
    
      require(["myModule"], function (mm) {
         console.log("inside", mm.myModule);
      });
    

    syncdefine函数为RequireJS定义一个模块,并立即与syncrequire一起使用。调用syncrequire会立即返回模块。它也可以通过RequireJS' require致电。

    此代码仅供参考。它不是一般的解决方案。