如何使用字符串作为模块名称

时间:2019-07-11 22:45:58

标签: javascript node.js node-modules

我正在尝试为我的node.js CLI应用程序编写一个插件系统。
该应用程序应该从.json文件中获取描述,并从.js文件中获取实际功能,所有这些都设置在特定的文件夹中。

应用程序在启动时检查此文件夹,并需要每个.json文件
根据json数据,它会加载一个包含 module.exports = {functions}

的.js文件。

如何在其他时间(在用户输入之后或10秒定时器之后)从主文件访问这些功能?

function fakeuserinput(x, y) {
  console.log(math.divide(x, y));
  })
}
setTimeout(fakeuserinput(10, 2), 10000); 

(第二个问题:是否有比使用eval()更好的方法?)

main.js

//commands is an array of all .json files
commands.forEach(function(cmd){ 
  // eval(cmd.module) = require('./plugins/'+cmd.module+'.js'); doesnt work
  require('./plugins/'+cmd.module+'.js');
  console.log(cmd.name+'\n'+cmd.module);
  // console.log(eval(cmd.module).eval(cmd.name)(10, 2));
  console.log(eval(cmd.name)(10, 2));
})

math.js

module.exports = {
  multiply: function (x, y) {
    return x * y;
  },
  divide: function (x, y) {
    return x / y;
  },
  add: function (numbers) {
    return numbers.reduce(function(a,b){
      return a + b
    }, 0);
  },
  subtract: function (numbers) {
    return numbers.reduce(function(a,b){
      return a - b
    }, 0);
  },
  round: function (x) {
    return Math.round(x);
  },
  squared: function (x) {
    return x * x;
  },
  root: function (x) {
    return Math.sqrt(x);
  }
}

divide.json

{
  "name": "divide",
  "module": "math",
  "commands": [
    [
      "how much is (integer) / (integer)",
      "how much is (integer) divided by (integer)",
      "what is (integer) / (integer)",
      "what is (integer) divided by (integer)",
      "(integer) / (integer)",
      "(integer) divided by (integer)"
    ]
  ],
  "description": "Divide x by y"
}

我能够在不知道函数名称的情况下加载函数:
main.js

//commands is an array of all .json files
commands.forEach(function(cmd){ 
  console.log(cmd.name);
  console.log(eval(cmd.name)(10, 2));
})

function divide(x, y) {
  return x / y;
}
function multiply(x, y) {
  return x * y;
}

但是当它在另一个文件的module.exports中时,我一直试图进入该功能。

json文件的代码->数组

var folder = './plugins/';
fs.readdir(folder, function (err, files) {
  if (err) {
    console.log('Couldn\'t read folder contents: '+err.message);
    return;
  }

  files.forEach(function (file, index) {
    if (file.substr(-5) == '.json') {
      let path = folder+file;
      fs.readFile(path, 'utf8', function (err, data) {
        if (err) {
          console.log('Couldn\'t read JSON file: '+err.message);
        }
        commands.push(JSON.parse(data));
        console.log('Command added: '+file.substr(0, file.length-5));
      });
    }
  });
});

错误消息: ReferenceError:数学未定义

1 个答案:

答案 0 :(得分:0)

下面是他的代码的修改后的版本,适用于我的用例。 这是一个非常混乱的修复程序,但是它可以工作。 希望它也能帮助其他人。

const { promisify } = require('util');
const { resolve } = require('path');
const fs = require('fs');
const readdir = promisify(fs.readdir);

function load (path) {
  return require(resolve(process.cwd(), path));
}

function plugincheck (arg1, arg2, arg3, arg4, arg5) {
  (async function () {
    const files = await readdir('commands');
    const commands = files
      .filter(file => file.endsWith('.json'))
      .map(file => load(`commands/${file}`));

    commands.forEach(command => {
      const plugin = load(`commands/${command.module}.js`);
      const fn = plugin[command.name];
      if (arg1 == command.name) {
        console.log(command.name+':'+fn(arg2, arg3, arg4, arg5));
      }
    });
  })().catch(err => {
    response.conlog('pluginloader', 'Couldn\'t scan plugins: '+err.message, 'error');
  });
}

setTimeout(simulate_user_input, 4000); 
function simulate_user_input () {
  plugincheck('root', 10)
}

setTimeout(simulate_user_input_two, 8000); 
function simulate_user_input_two () {
  plugincheck('divide', 10, 2)
}