bind
Функция bind предназначена для установки обработчиков.
Обработчики — особые функции, которые вызываются на различных этапах обработки запроса или при возникновении внештатных ситуаций в диалоге.
Принцип работы
Рассмотрим общий принцип работы обработчиков.
- Создается функция, которая как аргумент принимает объект
$context— текущий контекст обработки запроса. В теле функции производятся любые действия, необходимые по сценарию. - При установке функции в качестве обработчика при помощи функции
bindуказывается его тип. Тип определяет ситуацию, в которой обработчик будет вызван. - Также при установке обработчик привязывается к определенному пути в иерархии стейтов сценария. По умолчанию это корневой путь
/. - Обработчик и вызов функции
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: trueselectNLUResult
В одном сценарии возможно совместное использование нескольких типов правил активации. По умолчанию они срабатывают с заранее заданными приоритетами.
Обработчик 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 выполняется в нескольких случаях:
- В коде сценария возникло исключение, для которого не предусмотрен обработчик
onScriptError. - В ходе диалога возникла ошибка, для которой не предусмотрен обработчик
onDialogError. - Возникла непредвиденная ошибка сервера, не связанная с логикой сценария.
bind("onAnyError", function($context) {
var answers = [
"Что-то пошло не так.",
"Произошла ошибка. Пожалуйста, повторите запрос позже.",
"Все сломалось. Попробуйте еще раз."
];
var randomAnswer = answers[$reactions.random(answers.length)];
$reactions.answer(randomAnswer);
});После onAnyError обработчик postProcess не выполняется. Переход в другой стейт при помощи $reactions.transition невозможен.