JavaScript-действия
В JAICP DSL есть особые теги действий, которые позволяют вызвать из стейта отдельный сценарий. В этом подсценарии бот может реализовать любое поведение: выполнять произвольное число реакций, переходить по стейтам самого подсценария. При этом в основном сценарии эта сложная логика представлена как один тег.
Иногда в сценарии нужно выполнить действие без переключения контекста в отдельный подсценарий. В таком случае из стейта достаточно просто вызвать JavaScript-функцию, которая реализует нужное поведение.
Помимо сценарных действий JAICP DSL поддерживает JavaScript-действия (JS-действия).
Для них теги действий реализованы не как переход в подсценарий, а как обычный вызов функции внутри тега script
.
Как создать JS-действие
В этом разделе мы разработаем тег JS-действия, который:
- Принимает в качестве параметров два числа и формат ответа.
- Отправляет ответ с суммой этих чисел в указанном формате.
JavaScript-функция
- Авторизуйтесь в JAICP и выберите нужный проект.
- На панели управления слева перейдите в Редактор → Код.
- Создайте в директории
src
файлfunctions.js
и напишите в нем функцию для вашего тега.
function sumTwoNumbers(numberOne, numberTwo, answerFormat) {
var result = parseFloat(numberOne) + parseFloat(numberTwo);
if (!isNaN(result)) {
if (answerFormat === "number") {
$reactions.answer(result);
} else if (answerFormat === "full") {
$reactions.answer(numberOne + " + " + numberTwo + " = " + result);
}
} else {
$reactions.answer("Я не знаю, как посчитать " + numberOne + " + " + numberTwo + ".");
}
}
Разберем код функции:
- Функция принимает три аргумента.
- Параметры
numberOne
иnumberTwo
приводятся к числам при помощи функцииparseFloat
. Числа складываются, и сумма сохраняется в переменнуюresult
. - Если сумма имеет значение
NaN
, бот отправляет сообщение об ошибке, иначе — ответ в одном из форматов. - Если
answerFormat
имеет значение"number"
, то бот в ответе указывает только сумму, например: «7». ЕслиanswerFormat
имеет значение"full"
, то бот в ответе указывает полное выражение, например: «3 + 4 = 7».
В JS-действиях вы можете обращаться ко встроенным переменным только с помощью метода $jsapi.context
.
Настройки тега
Чтобы использовать сценарий выше как тег действия, его нужно описать в специальном JSON-файле с настройками.
- Создайте в директории
src
поддиректорию для тегов действий, напримерblocks
. - Создайте в директории
blocks
поддиректориюSumTwoNumbers
, а в ней файлblock.json
. - В файл запишите JSON-объект с настройками тега. Для JS-действий некоторые настройки отличаются:
Поле | Тип | Описание |
---|---|---|
customTagType | Строка | Тип тега действия: SC или JS . Чтобы сделать тег JS-действием, укажите значение JS . |
scenarioFile | Строка | Путь к нужному JavaScript-файлу относительно директории src . |
functionName | Строка | Название функции в файле scenarioFile , которая будет вызвана при использовании тега. Заменяет поле startState . |
Полный пример настроек:
{
"tagName": "SumTwoNumbers",
"customTagType": "JS",
"scenarioFile": "functions.js",
"functionName": "sumTwoNumbers",
"caption": {
"ru": "Сложить два числа",
"eng": "Sum two numbers"
},
"description": {
"ru": "Используйте этот блок, чтобы сложить два числа и отправить ответ со значением суммы.",
"eng": "Use this block to calculate the sum of two numbers and send a reply with the result."
},
"hint": {
"ru": "Сложить два числа и отправить ответ со значением суммы",
"eng": "Calculate the sum of two numbers and send a reply with the result"
},
"parameters": [
{
"name": "numberOne",
"type": "integer",
"required": true,
"localization": {
"ru": "Первое число",
"eng": "First number"
}
},
{
"name": "numberTwo",
"type": "integer",
"required": true,
"localization": {
"ru": "Второе число",
"eng": "Second number"
}
},
{
"name": "answerFormat",
"type": "string",
"required": true,
"localization": {
"ru": "Формат ответа",
"eng": "Answer format"
},
"userInterfaceField": {
"type": "select",
"options": [
{
"value": "number",
"localization": {
"eng": "Number only",
"ru": "Только число"
}
},
{
"value": "full",
"localization": {
"eng": "Full expression",
"ru": "Полное выражение"
}
}
]
}
}
]
}
Дальнейшие шаги не отличаются от сценарных действий:
-
Укажите путь к JSON-файлу в
chatbot.yaml
:customTags:
- src/blocks/SumTwoNumbers/block.json -
Используйте тег в сценарии через редактор кода или J‑Graph.
Преимущества JS-действий
С точки зрения разработки сценария через редактор кода JS-действия не дают больших преимуществ.
Если подключить файл с функцией через require
и вызвать ее из тега script
, поведение бота не изменится:
- JS-действие
- Функция
theme: /
state: SumTwoNumbers
q!: * [чему равно] @duckling.number::numberOne (плюс/$regex<\+>) @duckling.number::numberTwo *
SumTwoNumbers:
numberOne = {{$parseTree._numberOne}}
numberTwo = {{$parseTree._numberTwo}}
answerFormat = number
a: Посчитать для вас что-нибудь еще?
require: functions.js
theme: /
state: SumTwoNumbers
q!: * [чему равно] @duckling.number::numberOne (плюс/$regex<\+>) @duckling.number::numberTwo *
script:
sumTwoNumbers($parseTree._numberOne, $parseTree._numberTwo, "number");
a: Посчитать для вас что-нибудь еще?
Однако если сценарий разрабатывается через графический редактор J‑Graph, функцию можно использовать как блок действия и работать с ней в удобном интерфейсе.
Отличия от сценарных действий
Сценарное действие | JS-действие |
---|---|
Эквивалентно переходу в другой стейт через тег go! с передачей параметров. | Эквивалентно вызову функции через тег script . |
В одном стейте может быть не более одного тега. Если их больше, то будет выполнено только первое действие. | Может быть произвольное число тегов в одном стейте. Все действия будут выполнены. |
Значения параметров можно извлечь через объект $request.data.args . | Значения параметров можно извлечь как стандартные аргументы функции. |
Желательно предусмотреть параметры для стейтов основного сценария, в которые бот должен вернуться после действия (например, okState ). | После действия продолжает выполняться основной сценарий, поэтому параметры для стейтов предусматривать не обязательно. |