0

我正在尝试requirejs在 Apple TV 项目中使用。我们有很多requirejs为 web 编写的模块,如果我们可以重用它们会很酷。

Apple TV 平台有一定的限制,“按原样”使用 requirejs 是不可能的。常识中没有 DOM。我发现解决该问题的一种可能方法是:首先加载 require.js 本身,然后覆盖其.load()方法,因此每当require('foo')被调用时,它都会foo.js通过简单的 XHR 调用加载:

 requirejs.load = (context, moduleName, moduleUrl) ->
    reqModule = new XMLHttpRequest()
    reqModule.open('GET', appRoot+moduleUrl, true)
    reqModule.send(null)
    reqModule.onreadystatechange = ->
     if reqModule.readyState is 4 and reqModule.status is 200
          fn = (new Function(reqModule.responseText))() # parse module                             
          context[moduleName] = fn
          context.completeLoad(moduleName)

所以这适用于通常定义的模块,如下所示:

  define [], ->
       someField: 'empty field'

甚至适用于像这样的自我执行功能(配置了垫片):

  (myFoo = ->
      someField:"empty field"
  )()

例如Undercore.js包含在一个自执行的包装器中

但是,这不适用于像这样定义的模块:

 myFoo = ->
    someField:"empty field"

问题:我怎样才能使它适用于所有 3 种情况?在浏览器中使用时,requirejs 成功加载了所有这些。

我发现的一个解决方案是将函数包装在define块中,用于像上一个示例中那样的非包装模块,所以 fn = (new Function(reqModule.responseText))()我不会这样做:

fn = define [], (new Function("return "+reqModule.responseText))()

但是load对于第一种和第二种情况,这都会中断。有没有办法找出一个函数是否包装在一个自动执行的块中?如何区分前两种情况和最后一种情况?

4

2 回答 2

1

使用问题中的代码作为起点,我能够使以下代码正常工作。我没有 Apple TV,因此无法在 Apple TV 上进行测试。我已经在浏览器中测试过了。它能够加载您在问题中显示的所有 3 种类型的模块,前提是第 2 和第 3 模块具有适当的垫片。所以逻辑是合理的。缺少的部分是需要代替windoweval.call(window, ...)。在 Node.js 中,它将是global. 我不知道 Apple TV 中的等价物。

  requirejs.load = function(context, moduleName, moduleUrl) {
      var reqModule = new XMLHttpRequest();
      reqModule.open('GET', moduleUrl, true);
      reqModule.send(null);
      return reqModule.onreadystatechange = function() {
          if (reqModule.readyState === 4 && reqModule.status === 200) {
              eval.call(window, reqModule.responseText);
              return context.completeLoad(moduleName);
          }
      };
  };
于 2014-02-26T18:45:03.153 回答
0

如果我是你,我会使用Browserify

使用 node.js 风格的要求编写您的浏览器代码。

于 2014-02-26T00:36:56.863 回答