Узел: Сохранение имен функций в переменной и последующий их вызов

Я пишу приложение 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()}

При попытке добавить запланированную функцию я пробовал это со следующими синтаксисами:

  • mycronobj[элемент].schedulefunction()
  • mycronobj[item]функция расписания
  • mycronobj[элемент].schedulefunction

Ни один из них не работал для меня. Я попытался найти ответ на этот вопрос и попытался использовать оценка(), но это также не сработало правильно, в результате задача с первым расписанием ("* * * * *") была запланирована с последней функцией 'тестовая функция3'. применяется, также я действительно не хочу использовать eval, поскольку я читал, что это не очень хорошая практика, и ее можно избежать, если вы знаете, что делаете (очевидно, я не знаю).

Другие варианты, с которыми я столкнулся, - это использовать Window, которого нет в Node, или This, который я тоже не могу заставить работать.

Заранее спасибо.

К каким значениям должны относиться 'testfunction1' и 'testfunction2'? Это всего лишь строки, так как же они должны приводить к вызову функций?

Niels Abildgaard 17.03.2022 16:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
23
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Причина, по которой ваш код не работает, заключается в том, что 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 для прямого вызова функции, в отличие от подхода () => {какой-то код}.

David 18.03.2022 14:58

Другие вопросы по теме