如何处理具有条件要求的AMD模块?

时间:2013-01-15 15:32:16

标签: javascript requirejs amd js-amd

假设我有一个AMD模块,在某些环境中有条件地需要第二个模块:

define(["require"], function(require) {
  var myObj = { 
    foo: console.error.bind(console) 
  };
  if(browserEnv)
    require(["./conditional-polyfill"],function(polyfill){
      myObj.foo = console.log.bind(console,polyfill) ;
    });
  return myObj; //returns before conditional require is satisfied
});

问题是:在条件要求完成后,如何将define()调用延迟返回/回调?

即。以下代码失败:

require(["module-from-above"],function(logger){
  logger.foo("Hello!"); //console.error gets called
});

我对这个问题的解决方案的想法:

  • 如果我内联./polyfill,一切都会奏效。但是,这只是绕过了问题,并不适用于所有情况。我希望它模块化是有原因的。
  • 我可以返回一个Deferred对象,而不是myObj后来./conditional-polyfill完成的对象。这样可行,但是一直致电loggerDeferred.then(function(logger){ ... });真是太丑了。
  • 我可以为这个模块制作一个AMD加载器插件。一切准备就绪后立即调用回调。同样,这可以工作,但是自己的加载器插件不适用于我的构建工具。

我能想到的所有解决方案都比优秀的代码更糟糕。但是,我认为我的问题不是太牵强。那么,如何处理呢?

2 个答案:

答案 0 :(得分:3)

在“工厂函数”之外推送条件(在AMD社区中常用的名称来引用require和define的回调函数)

;(function() {

function factory(require, polyfill){
  var myObj = { 
    foo: console.error.bind(console) 
  }
  if(polyfill){
    myObj.foo = console.log.bind(console, polyfill)
  }
  return myObj
}

var need = ['require']

if(browserEnv){
  need.push("./conditional-polyfill")
}

define(need, factory)

})();

答案 1 :(得分:0)

我会像你说的那样使用Deferred。

延迟模式是解决此类问题的理想方法,因为它允许您以一致的方式将复杂的异步操作绑定在一起。

它会使您的代码变得更大,但与修改加载程序和构建工具相比,它是一个简单的解决方案。