# JavaScript API

Несколько блоков чат-бота выполняют ваш код на JavaScript. Код считает, разбирает ответы сторонних сервисов, меняет переменные и теги контакта, отправляет сообщения и решает, куда сценарию идти дальше. Этот раздел — справочник для того, кто пишет такой код.

## Где выполняется код

| Где | Когда запускается код | Что ему доступно, кроме функций |
|---|---|---|
| Блок [«Интерпретатор JavaScript»](https://support.watbot.ru/chatbots/blocks/developer/javascript) | Контакт дошёл до блока | Данные контакта |
| Блок [«HTTP-запрос»](https://support.watbot.ru/chatbots/blocks/developer/http), поле «Обработать ответ с помощью JavaScript» | Сервер ответил на запрос | Данные контакта и ответ сервера `response` |
| Блок [«Входящий Webhook»](https://support.watbot.ru/chatbots/blocks/developer/incoming-webhook) | На адрес блока пришёл запрос | Запрос `request`, а данные контакта — после того, как код его найдёт |
| Блок [«Чтение записей из Google Таблицы»](https://support.watbot.ru/chatbots/blocks/lists/google-sheet-reader), поле «JavaScript для обработки таблицы» | Блок нашёл строки в таблице | Данные контакта и найденные строки `sheet.data` |

Что лежит в этих данных — на странице [«Встроенные переменные»](https://support.watbot.ru/api/javascript/builtins). Функции одни и те же во всех блоках:

| Страница | Функции |
|---|---|
| [Переменные](https://support.watbot.ru/api/javascript/variables) | `getContactVariable`, `setContactVariable`, `deleteContactVariable`, `getGlobalVariable`, `setGlobalVariable`, `deleteGlobalVariable` |
| [Теги](https://support.watbot.ru/api/javascript/tags) | `getContactTags`, `hasContactTag`, `setContactTag`, `deleteContactTag` |
| [Сообщения и переходы](https://support.watbot.ru/api/javascript/messages) | `sendMessage`, `goToBlock`, `disableContinue` |
| [Выбор контакта](https://support.watbot.ru/api/javascript/contact) | `setContactById` и другие — только в блоке «Входящий Webhook» |
| [Подписи и Base64](https://support.watbot.ru/api/javascript/crypto) | `hash_hmac`, `base64_encode`, `base64_decode` |

## Как выполняется код

1. Код выполняется целиком на отдельном сервере. Функции не меняют контакта сразу, а запоминают, что сделать: какие переменные и теги записать, какие сообщения отправить, в какой блок перейти.
2. Код завершился без ошибки — бот записывает переменные и теги контакта и глобальные переменные бота, затем в порядке вызовов отправляет сообщения и переводит контакта в блок из `goToBlock`. После этого срабатывает связь «Продолжить», если код её не отключил.
3. Код завершился с ошибкой — не применяется ничего, даже то, что код успел вызвать до ошибки.

Внутри одного запуска функции чтения уже видят то, что код записал раньше: после `setContactVariable('букет', 'Розы')` вызов `getContactVariable('букет')` вернёт `'Розы'`, хотя контакту переменная ещё не записана.

Код запускается заново при каждом проходе через блок. Обычные переменные JavaScript (`var`) между запусками не сохраняются — то, что нужно запомнить, пишите в переменные контакта или в глобальные переменные бота.

## Язык

Код выполняется как JavaScript стандарта ES5. Из более новых стандартов нет:

- `let` и `const` — объявляйте переменные через `var`;
- стрелочных функций — пишите `function (x) { return x * 2; }`;
- шаблонных строк в обратных кавычках — склеивайте строки через `+`;
- классов, деструктуризации, `Promise`, `async`/`await`, `setTimeout`;
- методов из новых стандартов: `includes`, `startsWith`, `padStart`, `find`, `Object.assign`, `Array.from` и подобных. Вместо `includes` и `startsWith` подойдёт `indexOf`.

Есть всё из ES5: `JSON.parse` и `JSON.stringify`, `Math`, `Date`, методы строк и массивов `split`, `replace`, `trim`, `map`, `filter`, `forEach`, `reduce`, `indexOf`, `sort`. Директива `'use strict'` не мешает, но строгий режим не включает.

Запросов в сеть из кода сделать нельзя: `fetch`, `XMLHttpRequest` и `require` недоступны. Для запросов есть блок «HTTP-запрос».

### Даты

`Date` считает время в часовом поясе сервера, поэтому для расчётов берите методы с `UTC`: `getUTCHours()`, `getUTCDate()`. Строку вида `2026-01-31 12:00:00` (так выглядит `created_at`) `Date` не разбирает — замените пробел на `T` и добавьте `Z`:

```js
var created = new Date(created_at.replace(' ', 'T') + 'Z');
var days = Math.floor((new Date() - created) / 86400000);
```

### Регулярные выражения

Регулярные выражения выполняются движком RE2, и часть возможностей JavaScript в нём не работает. Код с такой записью остановится с ошибкой `Invalid regular expression`:

| Запись | Что это |
|---|---|
| `(?=...)`, `(?!...)` | Просмотр вперёд |
| `(?<=...)`, `(?<!...)` | Просмотр назад |
| `\1`, `\2` | Обратные ссылки на группу |

`\w`, `\b` и `\d` понимают только латиницу и цифры: `/\w+/` не найдёт слово «розы». Для русских букв перечислите их явно: `/[а-яё]+/i`.

## Ограничения

| Что | Предел |
|---|---|
| Длина кода | 16 384 символа в каждом поле с кодом |
| Время выполнения | 5 секунд. Код, который не уложился, останавливается с ошибкой `Script execution time exceeded` |
| `sendMessage` | 10 сообщений за запуск |
| `goToBlock` | Один вызов за запуск |
| Функции выбора контакта | Один вызов за запрос, только в блоке «Входящий Webhook» |

## Ошибки и отладка

Что произошло при запуске, видно в «Логе выполнения» в настройках блока: исходный код, значение последнего выражения, выполненные действия и текст ошибки.

Значение последнего выражения — главный инструмент отладки. Допишите в конец кода имя переменной или выражение, и его значение попадёт в лог. Объект или массив сначала превратите в строку, иначе в логе будет `[object Object]`:

```js
var bouquet = { name: 'Розы', count: 7 };
JSON.stringify(bouquet);
```

`console.log` ошибки не вызывает, но в лог ничего не пишет.

Куда уходит ошибка, зависит от блока:

| Блок | Что происходит при ошибке |
|---|---|
| «Интерпретатор JavaScript» | Текст ошибки уходит контакту в чат, связь «Продолжить» срабатывает |
| «HTTP-запрос» | Текст ошибки уходит контакту в чат, связь «Продолжить» не срабатывает |
| «Чтение записей из Google Таблицы» | Текст ошибки уходит контакту в чат, связь «Продолжить» не срабатывает |
| «Входящий Webhook» | Контакту ничего не уходит, блок отвечает на запрос кодом `422` с текстом ошибки |

В тексте синтаксической ошибки номер строки на единицу больше, чем в редакторе: ошибка `Line 4:5 Unexpected identifier` означает четвёртую строку минус одна — третью.

Ошибку можно вызвать и намеренно — `throw new Error('Нет цены')` остановит код, и ничего из сделанного им не сохранится. В блоках, которые отправляют текст ошибки в чат, контакт увидит `Error: Нет цены`.

> [!TIP]
> Проверяйте код в превью бота — кнопка «Проверить бота» в конструкторе. Так ошибку увидите вы, а не ваши клиенты.
