Динамически загружать функцию из файлов во время выполнения - PullRequest
0 голосов
/ 28 августа 2018

У меня есть некоторый код nodejs, который будет выступать в качестве арбитра в игре, в которую играют боты.

Каждый бот будет отдельным файлом с несколькими предопределенными functions с фиксированными именами (каждый бот будет называть свои функции такими же именами и аргументами, как PlayRound()).

Теперь я хотел бы, на runtime, добавить ботов в игру. Как я бы сказал арбитру botName1, он будет искать файл с именем botName1.js внутри папки с ботами, а затем сможет вызвать botName1.PlayRound() позже.

Поскольку require, похоже, работает только с литеральными статическими строками и не будет работать со значениями времени выполнения, есть ли способ сделать это?

пример кода:

const readline = require('readline');
const readLine = readline.createInterface({ input: process.stdin });

var players = []
var playerFiles = [];

readLine.on('line', (ln) => {

    var ws = ln.split(' ');

    if (ws[0].toLowerCase() === 'add') {
        players[players.length] = ws[1];
        // I would like to add the file corresponding to the name here
    } else if (ws[0].toLowerCase() === 'list'){
        console.log('There are currently ' + players.length + ' players registered:');
        for (var p in players) {
            console.log(players[p]);
        }
    } else if (ws[0].toLowerCase() === 'start'){
        // I would like to do this here
        for (var playerFile in playerFiles) {
            playerFiles[playerFile].PlayRound();
        }
    }

});

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Как подсказал @Kaito, возможно использование динамических требований. Но я бы никогда этого не предпочел, определенно нет, если вы не знаете, что может пойти не так. Динамическое требование оставляет ваше приложение открытым для ошибок времени выполнения, которые вы, возможно, не обработали, как, например, требование файла, которого нет (самый распространенный).

Я бы хотел опираться на то, что @Kaito и @Yash предложили / предоставили.

Решение

  1. Соберите все ваши файлы / функции бота на карте, которая отображает botname на botfilepath
  2. В вашей логике сначала проверьте, есть ли у вас botfile / botfunction, связанный с ботом, который присоединяется к
  3. Если да, то вы можете безопасно потребовать botfile во время выполнения .

В приведенном ниже примере я предполагаю, что все файлы ботов будут храниться в каталоге bots.

Пример * ** 1029 тысяча двадцать-восемь * const fs = require( "fs" ), path = require( "path" ), botsDir = path.join( __dirname, "bots" ); /** One time read to fetch all the bot files in bots dir */ const files = fs.readdirSync( botsDir ), /** Here we create the map of bot and bot file path */ availableBots = files .reduce( ( botMap, file ) => Object.assign( botMap, { [ file.replace(".js", "") ] : path.join( botsDir, file ) } ), {} ); // Your code const botThatWillBeJoiningAtRuntime = "BotC"; // This would be some calculation to determine bot that joins at runtime. /** Here we safely require the bot file only if we have one corresponding to the bot that is joining */ if ( availableBots[botThatWillBeJoiningAtRuntime] ) { const botFunc = require( availableBots[botThatWillBeJoiningAtRuntime] ); } Преимущество такого подхода -

Вы создаете файл op один раз в течение всего жизненного цикла приложения и накапливаете бот-файлы, тем самым сокращая дорогостоящие ios файлов, а затем для части if безопасно требуются бот-файлы в зависимости от того, есть ли в приложении файл бота для присоединяющегося бота.

Недостатком является -

Вам необходимо убедиться, что присоединяющийся бот имеет то же имя, что и botfile в каталоге bots.

0 голосов
/ 28 августа 2018

вы можете получить это с помощью пакета fs узла

 fs.readdirSync(PATHOFDIRECTORYCONTAININGFILEs)
       .forEach((file) =>  {
        var name = file.replace('.js', '');
        if(name === botname) {
          require('./' + file).PlayRound();
        }
    });

попробуйте это

 const readline = require('readline');
 const fs = require('fs);
 const readLine = readline.createInterface({ input: process.stdin });

 var players = []
 var playerFiles = [];

 readLine.on('line', (ln) => {

var ws = ln.split(' ');

if (ws[0].toLowerCase() === 'add') {
    players[players.length] = ws[1];
    //
} else if (ws[0].toLowerCase() === 'list'){
    console.log('There are currently ' + players.length + ' players 
        registered:');
    for (var p in players) {
        console.log(players[p]);
    }
} else if (ws[0].toLowerCase() === 'start'){
    // I would like to do this here

   fs.readdirSync(__diname)
   .forEach((file) =>  {
       for (var playerFile in playerFiles) {
         var name = file.replace('.js', '');
         if(name === playerFile) {
         require('./' + file).PlayRound();
        }
     }
  });
});
...