Свой код на JavaScript
Нода code_javascript исполняет ваш JavaScript как шаг графа. Это последняя дверь: то, для чего нет ноды и что не выражается шаблоном.
Сначала — не пишите код
Умолчание в Flow — нода, а не код, и это не идеология. Нода видна на холсте, её видит валидатор, её конфигурация попадает в журнал запуска, её ошибки разложены по кодам, и следующий человек поймёт граф, не читая программу. Код всего этого лишён: он непрозрачен для всех инструментов платформы и стоит дополнительный кредит за прогон.
| Задача | Чем делать | Где почитать |
|---|---|---|
| Собрать строку из нескольких значений | template | Шаблоны |
| Разобрать JSON, достать поле | json_parser | Шаблоны |
| Ветвление по условию | if / switch | Логика ветвлений |
| Пройти по списку | while_loop / array-ноды | Циклы |
| Сложить, посчитать, сравнить числа | ноды логики и строк | Ноды: обзор |
| Запрос к внешнему API | http_request | HTTP и веб |
| Табличные данные, CSV, агрегаты | df_* | Датафреймы |
Ссылки на разделы из последнего столбца: Шаблоны, Логика ветвлений, Циклы, Ноды: обзор, HTTP и веб, Датафреймы.
Код оправдан там, где выражение перестаёт быть выражением: нетривиальный разбор формата, рекурсивный обход дерева, алгоритм с состоянием и циклами, склейка десятка полей по правилам, которые проще записать, чем нарисовать. Признак «пора»: шаблон, в котором больше двух вложенных условий.
Что приходит и что нужно вернуть
Вы пишете тело функции, а не файл. Платформа оборачивает его так:
async function call(input, ...дополнительные порты) {
// ваш код
}
input— значение, пришедшее на порт Run. Строка, число, объект — что доставил провод данных.- Каждый дополнительный входной порт, добавленный на вкладке входов, становится параметром функции с тем же именем. Имена сортируются по алфавиту, так что порядок предсказуем.
- То, что вы вернёте, и есть выход ноды:
{{ nodes.<id>.output }}— это ровно возвращённое значение. Ничего оборачивать не надо. console.logи соседи попадают в журнал запуска ноды — это штатный способ отладки.get_var("имя")/set_var("имя", значение)читают и пишут переменные, объявленные нодами var в этом же графе. Незнакомое имя — ошибка, а не тихоеundefined(Состояние).
- Исполнение + данные
Ещё одно, что легко принять за поломку: шаблоны в теле кода не подставляются.
{{ secret.KEY }}, написанное внутри кода, останется буквальным текстом. Поле кода
намеренно не шаблонное — иначе фигурные скобки JavaScript пришлось бы экранировать, а
подставленный секрет попадал бы в журнал. Нужен ключ внутри кода — заведите его во входной
порт и передайте туда значение отдельной нодой.
Главное: код исполняется не в платформе
Ваш JavaScript выполняется в отдельном контейнере, у которого нет ничего, кроме среды исполнения.
- Платформа заранее считает всю политику безопасности — разрешённые хосты, запрещённые диапазоны адресов, потолки времени и памяти, предел размера кода.
- Готовое задание уходит в контейнер-исполнитель. Он не умеет ничего решать: набор разрешений, с которыми запускается ваш код, ему передан, а не выбран им, и посторонние разрешения он отвергает.
- Под каждый прогон поднимается свежий процесс. Результат и строки
console.*текут обратно потоком.
Что у этого контейнера есть и чего нет:
| Что | Есть? |
|---|---|
| Код платформы, её конфигурация | нет |
| Секреты рабочего пространства, ключи моделей | нет |
| Доступ к базе данных, к очереди, к векторному хранилищу | нет — он даже не в той сети |
| Файлы рабочего пространства, вложения чата | нет |
| Права на запись в файловую систему | нет, файловая система только для чтения |
| Сеть наружу | да, но по политике — см. ниже |
| Ограничение по памяти и процессорному времени | да, у контейнера жёсткие лимиты |
Зачем так, если код всё равно ваш. Затем, что «ваш код» — это код, который писали вы, а исполняет платформа, где живут данные других клиентов. Достаточно одной ошибки в движке JavaScript, чтобы прогон вышел за пределы песочницы. Если бы он выполнялся внутри рабочего процесса платформы, побег означал бы доступ к базе, к чужим секретам и к чужим файлам. Отдельный контейнер превращает тот же побег в попадание в одноразовую пустую коробку без сети к базе и без единого секрета внутри. Изоляция стоит нам сложности развёртывания, а вам — того, что администратор обязан поднять ещё один сервис; ровно поэтому без него исполнение кода не включается.
Сеть
fetch из кода работает. По умолчанию доступны любые публичные адреса; поле Allowed
hosts сужает список до перечисленных имён хостов. Приватные и loopback-адреса
заблокированы всегда, независимо от настройки, — та же защита, что у
http_request, и по той же причине: код, получивший адрес из
сообщения пользователя, не должен превращаться в сканер внутренней сети.
Пределы
| Что ограничено | Значение |
|---|---|
| Время одного прогона | 5 секунд по умолчанию, потолок 30 |
| Память | 128 МБ по умолчанию, потолок 512 |
| Размер кода | 64 КиБ |
| Одновременных прогонов на исполнитель | ограничено; при переполнении нода падает, а не встаёт в очередь |
Превышение времени — это отдельная ошибка «код не уложился в отведённое время», а не общий сбой: её видно в журнале и по ней понятно, что чинить.
Ошибки и биллинг
Выход ошибки у этой ноды выключен по умолчанию (в отличие от http_request): падение
вашего собственного кода — это, как правило, дефект, который надо чинить, а не ожидаемый
исход, который надо обрабатывать. Включается он тумблером Выход ошибки в основном
списке полей ноды (Ошибки нод).
Сообщение самой песочницы автор запуска видит: это его код и его ошибка. Собеседнику в чате оно не показывается никогда.
Что дальше
Ноды: обзор
Чем можно обойтись, не открывая редактор кода.
Шаблоны
Подстановки — первый инструмент до всякого кода.
Состояние
Переменные, которые код читает через get_var/set_var.
HTTP и веб
Запрос наружу без единой строки кода.
Кредиты
Из чего складывается цена запуска.
Своя установка
Кто включает исполнение кода и как.