Перейти к основному содержимому

bind

Функция bind предназначена для установки обработчиков.

подсказка
Обработчики — особые функции, которые вызываются на различных этапах обработки запроса или при возникновении внештатных ситуаций в диалоге.

Принцип работы

Рассмотрим общий принцип работы обработчиков.

  1. Создается функция, которая как аргумент принимает объект $context — текущий контекст обработки запроса. В теле функции производятся любые действия, необходимые по сценарию.
  2. При установке функции в качестве обработчика при помощи функции bind указывается его тип. Тип определяет ситуацию, в которой обработчик будет вызван.
  3. Также при установке обработчик привязывается к определенному пути в иерархии стейтов сценария. По умолчанию это корневой путь /.
  4. Обработчик и вызов функции bind помещается либо в отдельный файл с расширением .js, который импортируется в сценарий при помощи тега require, либо в тело тега init.
подсказка
При нахождении контекста бота в стейте, путь к которому начинается так же, как путь, к которому привязана функция-обработчик, она будет вызываться во всех случаях, разрешенных его типом.

Синтаксис

Функция bind принимает 4 аргумента.

АргументТипОписаниеОбязательный
typeСтрокаТип обработчикаДа
handlerФункцияФункция-обработчикДа
pathСтрокаАбсолютный путь для привязки обработчикаНет
nameСтрокаИмя обработчикаНет

Рассмотрим пример вызова функции bind:

bind(
"postProcess",
function($context) {
$context.session.lastState = $context.currentState;
},
"/Start",
"Remember last state"
);
  • Тип обработчика postProcess, переданный в качестве первого аргумента, означает, что он будет вызываться после основного цикла обработки запроса.
  • Функция, переданная как второй аргумент, задает целевое действие. В данном случае оно заключается в том, что путь к текущему стейту сохраняется в $session как предыдущий стейт.
  • Обработчик привязывается к пути /Start. Он будет вызываться в стейте /Start и во всех его дочерних стейтах — например, /Start/Hello, /Start/Hello/1 и т. д.
предупреждение
При привязке к корневому пути / обработчик будет вызван при нахождении в любом стейте сценария.

Обработчики этапов обработки запроса

Обработчики следующих типов вызываются в ходе общего цикла обработки запроса:

preMatch

Обработчик preMatch вызывается перед классификацией запроса. Ниже перечислены основные случаи его использования.

Принудительное изменение текущего стейта

В следующем примере при обработке запроса в стейте /Hello контекст будет переведен в стейт /Start. Это может быть полезно при переименовании стейтов для обратной совместимости версий сценария.

bind(
"preMatch",
function($context) {
$context.temp.targetState = "/Start";
},
"/Hello"
);

Изменение текста запроса

Обработчик из примера ниже добавляет к запросам от авторизованных клиентов суффикс, который позволит при помощи паттернов обработать их в стейтах, недоступных для клиентов без авторизации.

bind("preMatch", function($context) {
if ($context.client.hasActiveAuthorization) {
$context.request.query += " (клиент авторизован)";
}
});
предупреждение
Чтобы иметь возможность изменить текст запроса, задайте специальную настройку в конфигурационном файле chatbot.yaml:
nlp:
modifyRequestInPreMatch: true

selectNLUResult

В одном сценарии возможно совместное использование нескольких типов правил активации. По умолчанию правила срабатывают с заранее заданными приоритетами: сначала паттерны, затем интенты.

Если такое поведение нежелательно, с помощью обработчика selectNLUResult можно его изменить. Он вызывается после классификации запроса и переопределяет механизм выбора нужного правила.

preProcess

Обработчик preProcess вызывается после классификации запроса и определения целевого стейта, но перед выполнением действий, заданных в стейте. Например, он может быть использован для инициализации каких-либо данных или проверки предварительных условий для перехода в другие стейты.

В следующем примере предполагается, что в $session хранится параметр громкости устройства. Если громкость не задана, для нее устанавливается значение по умолчанию.

var DEFAULT_VOLUME = 40;

bind("preProcess", function($context) {
if (!$context.session.volume) {
$context.session.volume = DEFAULT_VOLUME;
}
});

postProcess

Обработчик postProcess выполняется после завершения обработки запроса и может быть использован, например, для добавления в ответ дополнительных полей или записи статистических данных.

В приведенном примере обработчик добавляет во все ответы бота в канале Telegram поле, которое указывает, что к ним применена разметка Markdown.

bind("postProcess", function($context) {
if ($context.response.channelType === "telegram") {
$context.response.replies = $context.response.replies.map(function(reply) {
if (reply.type === "text") {
reply.markup = "markdown";
}
return reply;
});
}
});
подсказка
Из postProcess также возможно использовать метод $reactions.transition для перехода обратно в сценарий и принудительного продолжения обработки запроса.

Обработчики ошибок

Обработчики ошибок служат для обработки внештатных ситуаций в ходе работы бота:

подсказка
В теле обработчиков ошибок в поле $context.exception.message содержатся сообщения возникших ошибок.

onScriptError

Обработчик onScriptError вызывается при возникновении необработанного исключения в коде на JavaScript. Также его можно использовать для настройки поведения при генерации собственных исключений при помощи инструкции throw.

Рассмотрим следующий пример использования обработчика для записи сообщения об ошибке в отчет по сессиям через метод $analytics.setSessionData.

bind("onScriptError", function($context) {
$analytics.setSessionData("Ошибка", $context.exception.message);
});
подсказка
После onScriptError может быть выполнен обработчик postProcess, а также переход в другой стейт при помощи $reactions.transition.

onDialogError

Обработчик onDialogError вызывается при возникновении ошибок сценария, не связанных с исключениями на JavaScript. Примеры таких ошибок:

ОшибкаСообщение об ошибке
Для запроса клиента не определен целевой стейт.No target state was determined for query
Сделан переход в несуществующий стейт.State not found for path <path>
Бот попал в бесконечный цикл переходов по стейтам.Infinite loop was detected for state <state> in postProcess transition
bind("onDialogError", function($context) {
if ($context.exception.message
&& $context.exception.message === "No target state was determined for query") {
$reactions.answer(
"Для запроса «" + $context.request.query + "» не найден стейт!"
);
}
});
подсказка
После onDialogError может быть выполнен обработчик postProcess, а также переход в другой стейт при помощи $reactions.transition.

onAnyError

Обработчик onAnyError выполняется в нескольких случаях:

  1. В коде сценария возникло исключение, для которого не предусмотрен обработчик onScriptError.
  2. В ходе диалога возникла ошибка, для которой не предусмотрен обработчик onDialogError.
  3. Возникла непредвиденная ошибка сервера, не связанная с логикой сценария.
bind("onAnyError", function($context) {
var answers = [
"Что-то пошло не так.",
"Произошла ошибка. Пожалуйста, повторите запрос позже.",
"Все сломалось. Попробуйте еще раз."
];
var randomAnswer = answers[$reactions.random(answers.length)];
$reactions.answer(randomAnswer);
});
предупреждение
После onAnyError обработчик postProcess не выполняется. Переход в другой стейт при помощи $reactions.transition невозможен.