Можно ли ждать WizardScene? - PullRequest
4 голосов
/ 10 июня 2019

Я разработал бота для Telegram, используя TelegrafJS , и я также использую библиотеку TelegrafInlineMenu для управления макетом меню.

Я зарегистрировал WizardScene для проверки ввода пользователя, здесь код:

const WizardScene = require('telegraf/scenes/wizard');
const Stage = require('telegraf/stage');
const projectController = require('../controllers/project.controller');

module.exports = function(bot) {

  const projectNameWizard = new WizardScene('projectName-wizard',
    (ctx) => {

      ctx.reply(ctx.i18n.t('projectName'));
      ctx.scene.session.project = {};

      //Project updating
      ctx.scene.session.project.oldName = ctx.match[1];

      //Keep customer reference
      ctx.scene.session.project.customerId = ctx.update.callback_query.from.id;
      return ctx.wizard.next();
    },
    async(ctx) => {

      //Get the name of the projec
      let oldPrName = ctx.scene.session.project.oldName;
      let newPrName = ctx.message.text;

      //Convalidate project
      if (ctx.message.text.length < 1 || ctx.message.text.length > 12) {
        return ctx.reply(ctx.i18n.t('invalidProjectName', {
          "characters": 12
        }));
      }
      ctx.scene.session.project.name = ctx.message.text;

      //Update the project fields
      await projectController.SaveProject(ctx.scene.session.project, ctx.update.message.from);
      let pr = await projectController.DisplayProjectDetails(ctx, newPrName);

      ctx.scene.leave();

      //Project was updated
      if (oldPrName !== undefined) {

        ctx.reply(ctx.i18n.t('projectUpdated'));
      }

      return pr;
    }
  );

  const stage = new Stage([projectNameWizard]);
  stage.command('cancel', (ctx) => {

    ctx.reply(ctx.i18n.t('operationCanc'));
    return ctx.scene.leave();
  });
  bot.use(stage.middleware())
}

Чтобы запустить мастер в меню, я использую следующий код:

projectEdit.simpleButton(ctx =>
  ctx.i18n.t('editName'), 'EDIT_PR_NAME', {
    doFunc: async ctx => {
      await ctx.scene.enter('projectName-wizard');
      console.log("hello world");
    },
  });

Мне нужно дождаться завершения WizardScene и затем выполнить console.log; проблема в том, что await перед ctx.scene.enter ничего не ждет, и сообщение hello world печатается мгновенно. Есть ли что-то, что позволило бы мне дождаться результата мастера? Если нет, как я могу справиться с этой ситуацией?

С уважением

1 Ответ

0 голосов
/ 21 июня 2019

"Мне нужно дождаться завершения WizardScene и затем запустить console.log, проблема в том, что ожидание перед ctx.scene.enter ничего не ждет, и выводится сообщение hello world мгновенно.

  • Есть ли что-то, что позволяет мне ждать результатов Волшебника?

  • Если нет, как еще я могу справиться с этой ситуацией? "

Я не использую Telegraf, но если каждая попытка не удалась, возможно, стоит рассмотреть возможность использования пользовательских событий , чтобы уведомить о готовности WizardScene. Это, вероятно, поможет вам решить проблему «Привет, мир печатается мгновенно ...»

Вместо await или сцены, которая будет готова, вместо этого прослушайте уведомление (событие) о готовности. Перейдите к той части кода, в которой сцена «готова», а затем отправьте событие, чтобы уведомить о завершении обработки кода.

Базовый пример пользовательского события:

<!DOCTYPE html>
<html>
<body>

<script>

//# define Event
var myReadyEvent = new CustomEvent("evt_WizardIsReady");

//# create Event handling function
function doWizardIsReady(evt)  
{ 
    alert("Got Event... : " + evt.type);
    console.log("hello world");
}

//# some function to trigger Event
function doSomething() 
{
    //# eg: prepare your scene here 

    //# and then dispatch at end of setup (before any RETURNs)
    document.body.dispatchEvent( myReadyEvent );
}

document.body.addEventListener("evt_WizardIsReady", doWizardIsReady, false);
setTimeout(doSomething, 6000); //represents waiting time for WIzardScene to be ready...

</script>

</body>
</html>

Глядя на ваш код ...

Вы хотите сделать: document.body.dispatchEvent( myReadyEvent );

  • До линии return pr;

  • Или попробуйте после строки bot.use(stage.middleware())

В качестве альтернативы рассмотрите возможность редактирования исходного кода Telegraf:

  • context.js - отредактируйте функцию enter в строке 43.

Попробуйте отправить событие перед строкой return handler(this.ctx, noop).

document.body.dispatchEvent( myReadyEvent );
return handler(this.ctx, noop)

Затем в основном HTML-коде (который загружает все эти внешние файлы JS) вы можете получить отправленное событие следующим образом:

<body>

<script type="text/javascript" src="context.js"></script>

<script>

//# define Event
var myReadyEvent = new CustomEvent("evt_WizardIsReady");
document.body.addEventListener("evt_WizardIsReady", doWizardIsReady, false);

//# create Event handling function
function doWizardIsReady(evt)  
{ 
    alert("Got Event... : " + evt.type);
    console.log("hello world");
}

</script>

</body>
  • См. Также: stage.js - Убедитесь, что enter работает в строке 37. Стоит ли редактировать это с помощью специального события?
...