Я пишу приложение node, которое использует node-cron для планирования запуска определенной функции в определенное время. В настоящее время код для этого встроен в основное приложение. Я хочу переместить конфигурацию запланированных задач в файл конфигурации, поэтому для этого мне нужно сохранить имена функций в переменной, поскольку задачи расписания вызывают ряд функций в разных модулях и т. д.
Для информации, синтаксис для планирования задачи cron таков:
cron.schedule('* * * * *', () => {functiontocall()});
Блок кода ниже показывает, как я в настоящее время сохраняю задачи в объекте и пытаюсь запланировать их с помощью node-cron.
mycronobj = [ {scheduletime : "* * * * *", schedulefunction : 'testfunction1'}, {scheduletime : "*/5 * * * *", schedulefunction : 'testfunction2'}, {scheduletime : "*/10 * * * *", schedulefunction : 'testfunction3'}, ] for (item in mycronobj) { cron.schedule(mycronobj[item].scheduletime, () => {mycronobj[item].schedulefunction()}); }
Однако это не работает, запланированные функции не запускаются. Я попытался сохранить имена функций в виде строки (как показано) или напрямую как
{scheduletime : "* * * * *", schedulefunction : testfunction1()}
При попытке добавить запланированную функцию я пробовал это со следующими синтаксисами:
Ни один из них не работал для меня. Я попытался найти ответ на этот вопрос и попытался использовать оценка(), но это также не сработало правильно, в результате задача с первым расписанием ("* * * * *") была запланирована с последней функцией 'тестовая функция3'. применяется, также я действительно не хочу использовать eval, поскольку я читал, что это не очень хорошая практика, и ее можно избежать, если вы знаете, что делаете (очевидно, я не знаю).
Другие варианты, с которыми я столкнулся, - это использовать Window, которого нет в Node, или This, который я тоже не могу заставить работать.
Заранее спасибо.
Причина, по которой ваш код не работает, заключается в том, что mycronobj[item]schedulefunction
- это строка, поэтому ее нельзя вызвать. Вам нужно превратить эту строку в ссылку на функцию с тем же именем.
Самое простое решение — использовать eval
, например:
for (item of mycronobj) {
cron.schedule(item.scheduletime, () =>
eval(`${item.schedulefunction}()`);
}
Однако это действительно плохая идея и позволяет выполнять произвольный код, который обычно считается очень плохо (tm).
Node предлагает более безопасную альтернативу этому, используя модуль вм, который может создать ограниченную песочницу, в которой может выполняться ваш код:
const vm = require("vm");
let context = vm.createContext({ foo });
for (item of mycronobj) {
cron.schedule(item.scheduletime, () =>
vm.runInContext(`${item.schedulefunction}()`, context);
}
Это ненамного лучше, так как все еще может разрешить выполнение произвольного кода, поэтому, безусловно, самый безопасный вариант — просто явно указать, какие именно функции разрешено вызывать:
const commands = {
testfunction1: () => console.info("I am 1"),
testfunction2: () => console.info("I am 2"),
testfunction3 // Reference existing function
}
function testfunction3() { console.info("I am 3"); }
for (item of mycronobj) {
let func = commands[item.schedulefunction];
if (!func) { throw new Error(`Unknown command: "${item.schedulefunction}"`); }
cron.schedule(item.scheduletime, func);
}
Преимущество этого также в том, что во время установки определяется, допустимы ли функции, а не только во время выполнения задания cron.
Спасибо за руководство, в итоге я выбрал несколько иной подход к решению проблем, но, используя ваши примеры выше, я оставил имена функций в объекте mycronobj, но как функции, а не строки (как в вашем примере), а затем исправил свой cron. ,schedule для прямого вызова функции, в отличие от подхода () => {какой-то код}.
К каким значениям должны относиться
'testfunction1'
и'testfunction2'
? Это всего лишь строки, так как же они должны приводить к вызову функций?