如何在包含它的那一刻立即加载requireJS模块

时间:2017-07-18 10:30:59

标签: javascript requirejs

我想在一个页面上使用两次模块,每次都使用不同的数据。在我的情况下,我需要模拟胡子模板,使用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>

使用init函数调用我希望“myApp”运行两次,一次data1数组和data2数组一次,但“myapp.init()”只运行一次,我只是用控制台测试。登录“myApp”。

代码是完全错误还是我错过了解AMD / requireJS的工作原理?

编辑:进一步测试:

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();
});

控制台输出是这样的:

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

这表示模块已加载,在胡子模板加载2次后,它运行myApp.js的脚本两次,但只有最后生成的id。

2 个答案:

答案 0 :(得分:1)

每次执行 $itemads = $this->paginate($itemads, ['contain' => ['Departments', 'Stores'],'group'=>'upc','fields'=>array("upc_count"=>"COUNT(`upc`)")]); 时,RequireJS都会注意到您希望在加载require(['app/myApp'], function(myApp){后执行回调。如果尚未提取模块,RequireJS将启动提取,记录回调,然后,在将来提取结束并且模块实例化时,它将调用回调。如果在模块实例化之前对同一模块发出多个请求,则RequireJS仅跟踪在模块最终准备好使用时需要调用的回调。您的日志显示这就是您的情况

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

    执行
  1. app/myApp,将var theId = el.id;设置为theId
  2. someId-428执行。
  3. require(['app/myApp'], function(myApp){执行,显示console.log("ID, logged inside reqJS:",theId);
  4. 执行
  5. someId-428,将var theId = el.id;设置为theId
  6. someId-248执行。
  7. require(['app/myApp'], function(myApp){执行,显示console.log("ID, logged inside reqJS:",theId);
  8. 但真正的执行顺序是这样的:

      执行
    1. someId-248,将var theId = el.id;设置为theId
    2. 执行
    3. someId-428并且RequireJS启动require(['app/myApp'], function(myApp){的加载,并记录回调以便将来调用它。
    4. 执行
    5. app/myApp,将var theId = el.id;设置为theId
    6. someId-248执行,但模块尚未加载,因此RequireJS将回调添加到加载require(['app/myApp'], function(myApp){时要调用的回调。
    7. app/myApp最终加载,因此回调被调用两次。但是,此时app/myApp的值为theId
    8. 关于最后一步,节点重要的是两个回调都访问同一个变量。如果您的代码位于问题前面显示的someId-248元素中,则script会声明全局变量。强制地,两个回调都必须访问同一个变量。如果您通过访问全局变量var theId获取ID,则myApp.init()中的内容相同。

      您可以使用IIFE解决问题,并将id传递给theId调用,并使用该函数代码中的参数。所以:

      myApp.init()

      IIFE使得每次调用上面的代码时(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的 new 变量。因此,RequireJS调用的回调每个都会看到自己独立的变量,并带有自己独立的值。

答案 1 :(得分:0)

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

require(['app/myApp'], function(MyApp){
    var myApp = new MyApp();
    myApp.init(theId);
});

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