2013-03-04 87 views
1

我想在AMD/Require站点中使用一些较旧的脚本。其中一些旧脚本通过使用document.write或tags.writeln来注入其他脚本。下面是发生了什么事的简化形式:阻止Require'ed脚本插入更多脚本标记

script1.js:

console.log('script1'); 
document.writeln("<script src='script2.js'></script>"); 

script2.js

console.log('script2'); 

如果我在经典的方式加载SCRIPT1,DOM同时显示脚本标记存在并且控制台输出显示两者都已执行:

<head> 
    <script src="script1.js"></script> 
</head> 
<body></body> 

但如果我通过RequireJS加载script1,DOM仅显示 script1标记。控制台输出显示SCRIPT1 执行,但document.writeln是显然忽略,因此SCRIPT2没有添加到DOM:

<head> 
    <script src="require-jquery.js"></script> 
    <script language="javascript"> 
     require(['script1'], function() { }); 
    </script> 
</head> 
<body></body> 

什么防止被插入到DOM这种额外的脚本?即使上面的工作正常,我怀疑我还会遇到加载顺序的其他问题。但我想了解这个漏洞,因为我知道RequireJS做什么不同,以防止加载额外的脚本。

我正在使用RequireJS的2.1.4版本。 Firefox和Chromium的行为是相同的。

编辑:我忘了提到,在真实场景中,'脚本2'的路径是基于某些服务器端逻辑的动态生成第一个脚本。我不能(很容易)改变这些旧的库,因为它们是由公司的不同部门控制的,并且是基于服务器端的部分动态的逻辑(再次,我不控制)。正如@ddotsenko建议的那样,也许我应该改写这个问题:如何采取一些依赖于注入脚本标记的遗留脚本,并使它们适合于试图通过使用AMD/RequireJS?建议的匀场方法接近但不起作用,因为依赖关系未知。

+0

看起来你来自.Net世界,其中document.write()是一个习惯性问题。我很惊讶你以前没有烧过你的手指。 DOM的准备状态和AMD规范的不同步意味着你最终必须在关闭HTML标签后尝试document.write()......问题可以重写为“当我用刀刺自己时,为什么刀让我的血液出来?“让我知道你是否愿意在你的编程方法上灵活一点,我会很乐意帮助你。 – ddotsenko 2013-03-05 18:55:19

+0

@ddotsenko :-)查看上面的修改。不,它不是.Net。但是,是的,在我过去的生活中,我太依赖于ASP.NET,并没有深入了解Javascript的实际操作。 – explunit 2013-03-05 20:09:15

回答

1

问题是document.write()在页面加载后(而RequireJS使用XHR)不起作用。

但是你可以用 “垫片” 预定义的旧模块的依赖 - http://requirejs.org/docs/api.html#config-shim

config.js

require.config({ 

    deps: ["main"], 

    shim: { 
     script1: { 
      deps: ['script2'], 
      exports: "someScript1Object" 
     } 
    } 
}); 

main.js

require(
    [ "script1" ], 
    function(someScript1Object) { 
     // ... 
    } 
); 

和控制台输出为

script2 
script1 

UPDATE。第二种变体:覆盖document.write/document。writeln

你可以使用来自ControlJS的技巧 - 覆盖document.write。试试这个代码:

require.docwrite = function(text){ 
    var aMatches = text.match(/src='([^']*)/i) || 
     text.match(/src="([^"]*)/i) || 
     text.match(/src=([^ >]*)/i); 
    if (aMatches) { 
     var url = aMatches[1]; 
     require([ url ]); 
    } 
} 

document.write = require.docwrite; 
document.writeln = require.docwrite; 
+0

看我上面的修改。我不知道提前给script2的路径,所以我不能将它作为依赖关系来填充。对不起,我忘了这部分。 – explunit 2013-03-05 12:10:17

+0

根据这个答案和上面的其他评论,我认为没有可能的解决方案,我的问题。即使陷印document.write并用require()调用替换也会将行为从同步更改为异步。但是,我接受这个答案,因为它可能是我将会得到的最接近的答案。 – explunit 2013-03-06 15:35:37