Лучшая практика для совместного использования экземпляра контроллера в приложении? - PullRequest
1 голос
/ 03 апреля 2020

Что делает приложение

Я пишу бот Telegram, используя Telegraf JS, пока я мы создали класс с именем Bot, который инициализирует бота middlewares и запускает его:

const Telegraf = require('telegraf');
const session = require('telegraf/session');

// Commands
const { commands } = require('../commands');

class Bot {

    constructor() {
        this.bot = new Telegraf(process.env.BOT_TOKEN);
        this.bot.catch(error => {
            console.error(`Bot error: ${error}`);
        });
    }

    // Init bot configuration
    async init() {

        // Set session
        this.bot.use(session.middleware());

        // Set commands
        this.bot.use(commands);
    }

    // Start the bot
    async start() {

        // Start the bot
        await this.init();
        this.bot.startPolling();
    }
}

exports.Bot = Bot;

входной файл app.js создает экземпляр Bot следующим образом:

const { Bot } = require('./logic/controllers/bot.controller');
let bot = new Bot();
await bot.start();

Проблема

Глядя на промежуточное ПО commands, я связал команды Composer с bot, поэтому по сути у меня есть:

const Composer = require('telegraf/composer');
const { Message } = require('../controllers/message.controller');
let msgController = new Message();

let messageCommand = new Composer();
messageCommand.action(/message-delete.+/, msgController.delete);

module.exports = messageCommand;

По существу, когда пользователь нажимает кнопку с обратным вызовом message-delete.message_id, запускается приведенная выше команда.

Проблема заключается в следующем:

Мне нужно использовать Telegram экземпляр бота внутри контроллера msgController, я фактически использовал контекст без передачи каких-либо параметров в .delete метод, но предположим, что я хочу сохранить экземпляр бота Telegram где-нибудь, который всегда должен быть доступен, как я могу это сделать?

Что я думал

Моя идея - передавать экземпляр бота Telegram каждый раз, когда я создаю экземпляр класса, например:

const { Markup } = require('telegraf');
const moment = require('moment');

// Models
const { MessageModel } = require('../models/message.model');

class Message {
    constructor(bot){
        this.bot = bot;
    }
}

, это хороший способ справиться с этим или есть лучшая практика?

1 Ответ

1 голос
/ 03 апреля 2020

Шаблон, который вы описали, называется внедрением зависимостей и является одним из способов выполнения описанного требования. В этом подходе нет ничего принципиально неправильного.

Альтернативный способ - использовать событийную архитектуру , где приложение представляет собой eventEmitter, а бот Telegram слушает и реагирует на эти события.

Вот как реализовать подход, управляемый событиями.

  1. В app.js должен быть определен источник событий и передан экземплярам модулей:
const EventEmitter = require('events');

class appEvents extends EventEmitter {}

const appEvents = new appEvents();

let bot = new Bot(appEvents);
let myMiddleware = new MyMiddleware(appEvents);
bot.js слушает и реагирует на события:
appEvents.on('event', () => {
  console.log('an event occurred!');
});
Модули промежуточного программного обеспечения и генерируют события всякий раз, когда это необходимо:
appEvents.emit('event');

Здесь, в отличие от решения для внедрения зависимостей, связь между модулями слабая: модули промежуточного программного обеспечения явно не вызывают бот вообще.

Эта слабая связь может быть преимуществом, так как каждый модуль заботится о своем бизнесе, не беспокоясь о том, что будет дальше. В больших приложениях, однако, может быть сложно узнать, что происходит, когда происходит событие (так как несколько частей приложения могут прослушивать и реагировать на него.

В Интернете много литературы о плюсах и минусах обоих подходов, до вас, чтобы составить собственное мнение.

...