Javascript 如何在包含requireJS模块时立即加载该模块

Javascript 如何在包含requireJS模块时立即加载该模块,javascript,requirejs,Javascript,Requirejs,我想在一个页面上使用一个模块两次,每次使用不同的数据。在我的例子中,我需要一个小胡子模板中的模块,该模板使用了2次,例如: {{> template-requiretest }} {{> template-requiretest }} 在我的胡子模板中,我得到了如下内容: <script> var data1 = [x,y,z]; var data2 = [x,y,z]; var theId = (some random id); r

我想在一个页面上使用一个模块两次,每次使用不同的数据。在我的例子中,我需要一个小胡子模板中的模块,该模板使用了2次,例如:

{{> template-requiretest }}
{{> template-requiretest }} 
在我的胡子模板中,我得到了如下内容:

<script>
    var data1 = [x,y,z];
    var data2 = [x,y,z];
    var theId = (some random id);

    require(['app/myApp'], function(myApp){
        myApp.init();
    });
</script>
require(['app/myApp'], function(MyApp){
    var myApp = new MyApp();
    myApp.init(theId);
});
控制台输出如下:

xyz.html:131 ID, set in mustache:  someId-428
xyz.html:181 ID, set in mustache:  someId-248
myApp.js:3 ##### running the script now #####
myApp.js:4 ##### using ID: someId-248  #####
xyz.html:134 ID, logged inside reqJS: someId-248
xyz.html:184 ID, logged inside reqJS: someId-248

这表示模块已加载,在Mustach模板加载2次后,它将运行myApp.js脚本两次,但仅使用最后生成的id。

每次执行
require(['app/myApp'],function(myApp){
,RequireJS注意到,您希望在加载
app/myApp
后执行回调。如果模块尚未提取,RequireJS将启动提取,记录回调,然后在将来提取完成且模块实例化后,它将调用回调。如果之前出现了对同一模块的多个请求模块已经实例化,RequireJS只跟踪在模块最终准备好使用时需要调用的回调。您的日志显示这就是您的情况

我认为你直觉上期望或想要的是执行的顺序:

  • var theId=el.id;
    执行,将
    theId
    设置为
    someId-428
  • require(['app/myApp'],函数(myApp){
    执行
  • console.log(“ID,记录在reqJS内:”,theId);
    执行,显示
    someId-428
  • var theId=el.id;
    执行,将
    theId
    设置为
    someId-248
  • require(['app/myApp'],函数(myApp){
    执行
  • console.log(“ID,记录在reqJS中:”,theId);
    执行,显示
    someId-248
  • 但真正的执行顺序是这样的:

    <script>
        var data1 = [x,y,z];
        var data2 = [x,y,z];
        var theId = (some random id);
    
        require(['app/myApp'], function(myApp){
            myApp.init();
        });
    </script>
    
    require(['app/myApp'], function(MyApp){
        var myApp = new MyApp();
        myApp.init(theId);
    });
    
  • var theId=el.id;
    执行,将
    theId
    设置为
    someId-428
  • require(['app/myApp'],函数(myApp){
    执行,RequireJS启动
    app/myApp
    的加载,并记录回调以在将来调用它
  • var theId=el.id;
    执行,将
    theId
    设置为
    someId-248
  • require(['app/myApp'],函数(myApp){
    执行,但模块尚未加载,因此RequireJS将回调添加到加载
    app/myApp
    时要调用的回调中
  • app/myApp
    最终加载,因此回调被调用两次。但是,此时
    theId
    的值为
    someId-248
  • 关于最后一步,重要的是要确定两个回调都在访问同一个变量。如果您的代码在
    脚本
    元素中,如您前面的问题所示,则
    var theId
    声明一个全局变量。强制地说,两个回调都必须访问同一个变量。在
    myApp.ini中是相同的t()
    如果通过访问全局变量
    theId
    获取id

    您可以使用IIFE解决这个问题,将id传递给您的
    myApp.init()
    调用,并在该函数的代码中使用参数。因此:

    (function () {
      var random = Math.floor((Math.random() * 1000) + 1);
      var el = document.getElementById('someId');
      el.id += '-'+random;
      var theId = el.id;
      console.log("ID, set in mustache: ",theId);
    
      require(['app/myApp'], function(myApp){
        console.log("ID, logged inside reqJS:",theId);
    
        myApp.init(theId); // Pass the id to your function.
      });
    }());
    
    IIFE使得每次调用上面的代码时,ID都是IIFE的一个新变量。因此,RequireJS调用的回调都会看到自己的独立变量,以及自己的独立值。

    调用
    require(['app/myApp'],function(myApp){…});
    多次只会导致
    app/myApp
    运行一次。因此,任何两个这样的调用都将给出同一个对象;如果您尝试将它们作为具有不同ID的单独对象处理,则不会起作用。如果您想要单独的对象,请执行以下操作:

    <script>
        var data1 = [x,y,z];
        var data2 = [x,y,z];
        var theId = (some random id);
    
        require(['app/myApp'], function(myApp){
            myApp.init();
        });
    </script>
    
    require(['app/myApp'], function(MyApp){
        var myApp = new MyApp();
        myApp.init(theId);
    });
    

    当然,更改脚本
    app/myApp
    ,使其返回应用程序的构造函数,而不是应用程序本身。

    此处显示的代码与OP的代码有相同的问题:
    myApp.init(theId)
    将使用相同的
    theId
    @Louis值调用两次。我不清楚OP希望如何调用代码两次。当然,他们可以这样做,并且每次可以使用不同的ID调用代码;我只调用了一次,所以这不是我的问题。重点是每次都需要创建一个新对象,所以你不能只调用一次主动使用惰性模块加载提供的对象。