即时重新包含模块

Re-including a module on-the-fly

我目前正在处理 SonarQube 为 Node.js 应用程序确定的技术债务。我的应用程序允许在实时数据源和模拟数据源之间进行即时切换。为此,我从缓存中销毁了之前的 "require" 并重新获取它。当 运行 SonarQube 不喜欢 "require" 语句。它确实建议 "import" 语句。但是,这可能不适合这种情况。

现有代码的简化版本:

var config = require('../config');
var polService = require(config.polService);
var root = require('../root');
function doingStuff(liveOrMock) {
    setEnvironment(liveOrMock);
    delete require.cache[require.resolve(root.path + ‘/config’)];
    config = require('../config');
    polService = require(config.polService);
}

setEnvironment函数集process.env.NODE_ENV = liveOrMock,用在config.js中。我们使用 module.exports = localOptions[process.env.NODE_ENV]; 导出 config 模块此代码从 JSON 中选择一个密钥对。返回的值用于选择哪个模块用于 restService。

能够更改正在使用的模块是为了 polService 是代码的目的。

更改您的 config 模块以导出函数,然后在需要更改环境时调用此函数。

为了使 polService 成为动态模块,您可以使用 dynamic import(). import() is not supported natively, but you can use this Babel plugin(它与 webpack 一起使用)来转换它。

config.js:

export default () => {
  // ...
  return localOptions[process.env.NODE_ENV];
}

主模块:

import getConfig from '../config';

let config = getConfig();

function doingStuff(liveOrMock) {
  setEnvironment(liveOrMock);
  config = getConfig();
  return import(config.polService).then(result => {
    polService = result;
  });
}

请记住,现在 doingStuff 函数是异步的(即 returns 一个承诺),因此您不能直接调用它并立即访问 polService。您必须使用 then() method, or using await in an async function.

等待它

如果您的 polService 模块数量有限,预先导入所有模块可能是更好的选择,并且在 doingStuff 函数中只需切换哪个 polService变量指的是.

import getConfig from '../config';
import polService1 from '../polService1';
import polService2 from '../polService2';
import polService3 from '../polService3';

const polServices = { polService1, polService2, polService3 };

let config = getConfig();
let polService = polService1;

function doingStuff(liveOrMock) {
  setEnvironment(liveOrMock);
  config = getConfig();
  polService = polServices[config.polService];
}