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