2012-08-25 37 views
1

我有一个requirejs项目已被优化成单个文件,我正在同步加载。代码按预期加载,但模块仍在加载异步(它们在加载过程中稍后才可用),并且它对于我希望它可以使用的一些遗留代码造成问题。同步使用requirejs

鉴于下面的代码,是否有任何方法使main-build的方法在加载之后立即可用,并在legacy_code.js加载之前立即可用?

<script type="text/javascript" src="/scripts/vendor/require.js"></script> 
<script type="text/javascript" src="/scripts/main-build.js"></script> 

<!-- At this point, the code is set up and it will be invoked later --> 
<!-- ...but the next file requires to access methods in the modules.--> 

<script type="text/javascript" src="/script/legacy_code.js"></script> 

如果出现最坏的情况,我可以写我自己的define()require()版本(这也将释放大量的带宽,因为所有这将需要做的是目录和调用模块),但我希望有一种内置的方式来做到这一点。

回答

1

在这里回答我自己的问题。经过了很长一段时间,我看不到任何方式来加载Requirejs代码或加载后立即调用模块。所以我最终写了一些代码来暂时覆盖requiredeclare方法。它适用于我的用例,但如果其他人需要它可能需要更改。我相信它可以比现在更优化,但它可以工作。

你可以找到代码on GitHub,我会尽量保持。

此时的代码如下所示:

(function() { 
    var self = {}, 
     originalDefine = window.define, 
     originalRequire = window.require, 
     modules = []; 

    var define = function (id, deps, fn) { 
     if (id !== 'requireLib' && id !== 'text') { 
      modules.push({"id": id, "deps": deps, "fn": fn}); 
     } 
    }; 



    var require = function (deps, fn) { 
     var sortedModules = [], 
      unsortedModules = [], 
      resolvedDeps = {}, 
      maxAttempts = 1000, 
      module, 
      dep, 
      depList, 
      canAdd, 
      i, 
      j; 

     unsortedModules = ([]).concat(modules); 
     while (unsortedModules.length > 0 && --maxAttempts > 0) { 

      for (i = unsortedModules.length - 1; i >= 0; i--) { 
       canAdd = true; 
       module = unsortedModules[i]; 

       for (j = 0; j < module.deps.length; j++) { 
        dep = module.deps[j]; 
        if (resolvedDeps[dep] === undefined) { 
         canAdd = false; 
         break; 
        } 
       } 
       if (canAdd) { 
        resolvedDeps[module.id] = module; 
        sortedModules.push(unsortedModules.splice(i,1)[0]); 
       } 
      } 
     } 

     for (i = 0; i < sortedModules.length; i++) { 
      module = sortedModules[i]; 
      depList = []; 
      for (j = 0; j < module.deps.length; j++) { 
       depList.push(resolvedDeps[module.deps[j]]); 
      } 
      resolvedDeps[module.id] = module.fn.apply(this, depList); 
     } 

     depList = []; 
     for (i = 0; i < deps.length; i++) { 
      depList.push(resolvedDeps[deps[i]]); 
     } 

     fn.apply(this, depList); 

     window.define = originalDefine || function() {}; 
     window.require = originalRequire || function() {}; 
    }; 

    window.define = define; 
    window.require = require; 
    window.require.config = function() {}; 

    return self; 
}()); 
+0

太糟糕了,它不能按预期同步工作:http://plnkr.co/edit/ErIS1MCgS9vcxEnw9AKt?p=preview –

+0

要求使用AMD语法来加载模块,而不是Common.js语法。有关使用信息,请参阅[文档](http://requirejs.org/docs/api.html)。除非你正在使用AMD项目,否则我不建议开始使用它:common.js几乎赢得了模块大战。 – Andrew

+0

你知道任何可以使用commonjs加载模块的库,但是(!)是同步的吗? –

-3

如果您使用jQuery.ajax()函数使用Jquery和某个服务器端函数,则默认情况下这些调用是异步的。

http://api.jquery.com/jQuery.ajax/

您可以设置异步:假的jQuery.ajax()函数。

希望这会有所帮助。

+0

感谢。我正在使用jQuery,但没有任何ajax /请求方法。 – Andrew

0

要做到这一点,而不必重写define()require()最简单的方法,肯定只是对wrap your legacy code in an AMD并指定main-build.js模块定义为一个依赖。

我知道这在技术上不是'同步的',但是它应该能够实现你正在寻找的东西 - 遗留代码仅在require模块加载后才会被调用。

+0

在这种情况下,这是不可能的。 'legacy_code.js'实际上在几十页上,对每个页面都是唯一的。我现在所做的是设置一种Facade模式,它复制旧的遗留代码,并简单地记录这些调用,以便稍后在模块加载时执行这些调用,但这样做让我感到后退,因为这样做是因为这些模块显然已经存在,只要'main-build.js'已经被载入,应该可以访问这些模块。 – Andrew