3

是否可以在运行时修改 requirejs(或任何 AMD 加载器)配置?

例如,我有两个日志模块:一个简单地包装 console.log,另一个记录到服务器。我希望模块只需要 log ( require(['log'], function(log) { ... });) 而不在乎它使用的是哪个记录器。

我可以在require的主配置中将'log'设置为一个包,这很好用。但我宁愿根据几个条件在 main.js 中设置此选项。就像是:

if( ... ) {
    require.config({
        packages: [
            { name: 'log', location: 'app/base/utils/consolelog' }
        ]
    });
}

但这似乎不起作用。有没有办法做到这一点,或者我是否将 requirejs 的功能作为依赖注入框架?

干杯

4

1 回答 1

4

任何依赖注入框架的一般工具是,您有一种简单的方法来配置它将在运行时解析哪种依赖容器,并且它只构建一次并在应用程序的生命周期内保持静态。

这样做是为了避免在应用程序中的某个时刻出现依赖关系可能发生变化的情况。有这样一种想法,即您的一个或所有应用程序源可能需要在它们使用来自容器的一些或任何依赖项之前请求许可,而不是仅仅在容器上运行,这是一个糟糕的想法,它有很多缺点。主要缺点是您知道,其中的任何引用都accounts.all().each().withdraw(billing.MONTHLY_SERVICE_FEE).return()可能在任何时候无明显原因地表现不同。如果Accounts更改并且new Accounts().all()没有返回任何帐户,或者billing.MONTHLY_SERVICE_FEE突然更改并且您向某些帐户收取 X 金额而向其他帐户收取 Y,那将是很糟糕的。

所以,简短的回答是否定的,你不能动态配置 RequireJS。RequireJS 将始终只加载一个模块一次,因此回调返回值始终是一个静态对象,或者如果您愿意,当您查看模块源时,您知道它define()只会在整个生命周期内被评估一次文档。

以下是几种非常简单的方法,用于在运行时抽象对象的特定实现。您只需创建几个带有回调的模块,这些模块返回具有相同公共接口但行为不同的对象,然后您可以静态或动态地解决要返回的对象。

// core/logging/base.js
define(function() {
  var static;
  var base =  {
      _log: undefined,
      create: function(name) {},
      // ..
  }

  return base;
});

// core/logging/client.js
define(function(['core/logging/base'], function(base) {
  var client = extend(base, {_log: console.log});
  return client;
});

// core/logging.js
define(['core/logging/server', 'core/logging/client', 'core/conf/settings'], 
  function(server, client, environment) {
  if(settings.LOGGER === 'server') {
    return server;
  } else {
    return client;
  }
};

// app/foo.js
define(['core/logging'], function(logging) {
  var log = logging.createLog('foo');
  log.info('bar');
  // > INFO foo: bar
  // or...
  // POST http://server/log {type: 2, name: 'foo', message: 'bar'}
}

有几种方法可以设计这种支持,但是这种方法很简单,并且适用于您的特定情况。通常,您可以在模块中静态执行此解析,也可以通过 getter 函数在任何块中动态执行此解析,并且模块回调本身也可以返回构造函数或函数,而不仅仅是对象。

于 2013-02-14T19:21:34.333 回答