Выходные данные и работа с контекстомBETA
В процессе выполнения блоков интеграции важно точно описывать структуру возвращаемых данных и управлять состоянием выполнения. В этом разделе описаны типы выходных переменных, а также механизм использования контекста для постраничной обработки данных (пагинации).
Типы данных выходных переменных
В представленном ниже примере интеграция состоит из нескольких блоков, каждый из которых выполняет определенную задачу, например, получение данных из API или их обработку. Каждый блок имеет поля ввода, используемые для настройки запроса, и поля вывода, содержащие результаты выполнения.
В каждом блоке определены переменные output_variables
, которые формируют выходные данные. Эти переменные могут быть различных типов, включая числа, строки, массивы, объекты, а также массивы объектов.
Особенности описания выходных данных
- Для примитивных типов (
Long
,Double
,Boolean
,String
) и массивов примитивов (LongArray
,DoubleArray
,BooleanArray
,StringArray
) необходимо указать только тип данных и название переменной. - Для объектов (
Object
) и массивов объектов (ObjectArray
) необходимо дополнительно указать структуру вложенных полей.
В таблице ниже представлены возможные типы переменных и их значения.
Тип данных | Описание | Пример |
---|---|---|
Простые типы | ||
Long | Целое 64-битное число | 1234 |
Double | 64-битное число с плавающей точкой | 1.02 |
Boolean | Логическое значение | true /false |
String | Строка | 'example' |
BigInteger | Целое число произвольной длины | 123456789123456789123456789 |
BigDecimal | Десятичное число с высокой точностью | 123456.789123456789 |
DateTime | Дата и время, аналог Instant в Java/Kotlin | 2024-12-31T23:59:59Z |
Массивы простых типов | ||
LongArray | Массив целых 64-битных чисел, может содержать значения null для пропущенных данных | [12, null, 34, 56] |
DoubleArray | Массив чисел с плавающей точкой, может содержать значения null | [1.01, null, 1.02] |
BooleanArray | Массив логических значений, может содержать null | [true, null, false] |
StringArray | Массив строк, может содержать null | ['one', null, 'two'] |
BigIntegerArray | Массив больших целых чисел | [123456789123456789, 999999999999999999] |
BigDecimalArray | Массив десятичных чисел высокой точности | [123.456789, 987654.3210001] |
DateTimeArray | Массив объектов даты-времени Instant | ['2023-01-01T10:00:00Z', '2023-01-02T15:30:00Z'] |
Специальные/сложные типы | ||
Object | Объект с вложенными полями | Пример представлен ниже |
ObjectArray | Массив объектов, где каждый объект может иметь вложенные поля разных типов | Пример представлен ниже |
File | Файл, представленный как поток данных | Бинарный поток файла PDF или CSV |
Пример использования объекта Object
:
{
type: "Object",
name: "project",
struct: [
{ type: "String", name: "id" },
{ type: "String", name: "key" },
{ type: "String", name: "name" },
{ type: "String", name: "description" },
{ type: "String", name: "projectCategory" }
]
}
Пример использования массива объектов ObjectArray
:
{
type: "ObjectArray",
name: "comment",
struct: [
{type: "String", name: "id"},
{type: "String", name: "author"},
{type: "String", name: "body"}
]
}
Пример структуры выходных данных
В каждом блоке выходные переменные указываются в поле output_variables
. Массив output_variables
описывает структуру данных, которые возвращает блок. Эти переменные могут быть использованы в других блоках или переданы во внешние сервисы.
Ниже представлен пример для блоков TEST_1 и TEST_2, в котором данные возвращаются в формате массивов, где каждый элемент соответствует соответствующему типу из output_variables
.
В примере:
- Первая переменная имеет тип Long и значение null
- Вторая переменная — это массив типа LongArray, и его значение пустое
- Далее идет множество других переменных, каждая из которых имеет тип, указанный в
output_variables
и может содержать данные или null
integration = {
schema: 1,
meta: {
key: '22',
name: 'lazy_test_2',
description: 'lazy_integration_test_2'
},
blocks: [
{
meta: {
key: 'TEST_1',
name: 'Создаёт TEST_1',
description: 'через TEST_1'
},
inputFields: [{
key: "limit",
type: "text",
label: "Введи limit",
required: true
}],
executePagination: (z, bundle, context) => {
const limit = Number(bundle.inputData.limit);
var state;
if (context === undefined) {
state = 1;
} else {
state = context + 1;
}
var hasNext = state < limit;
return {
output_variables: [
{
type: "Long",
name: "var_long"
}, {
type: "LongArray",
name: "var_long_array"
}, {
type: "Double",
name: "var_double"
}, {
type: "DoubleArray",
name: "var_double_array"
}, {
type: "Boolean",
name: "var_boolean"
}, {
type: "BooleanArray",
name: "var_boolean_array"
}, {
type: "String",
name: "var_string"
}, {
type: "StringArray",
name: "var_string_array"
}, {
type: "Object",
name: "var_object",
struct: [{
type: "String",
name: "field1"
}, {
type: "Long",
name: "field2"
}]
}, {
type: "ObjectArray",
name: "var_objects",
struct: [{
type: "Object",
name: "field1",
struct: [{
name: "field1_1",
type: "String"
}, {
name: "field1_2",
type: "Stringer"
}]
}, {
type: "String",
name: "field2"
}]
}
],
output: {
a: 100 + state,
state: state
},
state: state,
hasNext: hasNext
};
}
}, {
meta: {
key: 'TEST_2',
name: 'Создаёт TEST_2',
description: 'через TEST_2'
},
inputFields: [{
key: "limit",
type: "text",
label: "Введи limit",
required: true
}],
executePagination: (z, bundle, context) => {
const limit = Number(bundle.inputData.limit);
var state;
if (context === undefined) {
state = 1;
} else {
state = context + 1;
}
var hasNext = state < limit;
return {
output_variables: [
{
type: "Long",
name: "var_long"
}, {
type: "LongArray",
name: "var_long_array"
}, {
type: "Double",
name: "var_double"
}, {
type: "DoubleArray",
name: "var_double_array"
}, {
type: "Boolean",
name: "var_boolean"
}, {
type: "BooleanArray",
name: "var_boolean_array"
}, {
type: "String",
name: "var_string"
}, {
type: "StringArray",
name: "var_string_array"
}, {
type: "Object",
name: "var_object",
struct: [{
type: "String",
name: "field1"
}, {
type: "Long",
name: "field2"
}]
}, {
type: "ObjectArray",
name: "var_objects",
struct: [{
type: "Object",
name: "field1",
struct: [{
name: "field1_1",
type: "Long"
}, {
name: "field1_2",
type: "String"
}]
}, {
type: "String",
name: "field2"
}]
}
],
output: [[
null,
[],
null,
[],
null,
[],
null,
[],
{
field1: null,
field2: null
},
[{
field1: {
field1_1: null,
field1_2: null
},
field2: null
}]
], [
1234,
[12, null, 34, 56, 78],
1.02,
[1.01, null, 1.02, 1.03],
true,
[true, null, false, false, true],
'1234',
['12', null, '34', '56'],
{
field1: '1',
field2: 2
},
[{
field1: {
field1_1: '12',
field1_2: '34'
},
field2: '2'
}]
]],
state: state,
hasNext: hasNext
};
}
}
],
connections: []
}
Использование контекста в интеграции
В представленном выше примере интеграции каждый блок имеет функцию executePagination
, которая принимает три параметра:
z
— вспомогательный объект с системными методамиbundle
— содержит входные данные и параметры авторизацииcontext
— объект, в котором хранится информация о текущем состоянии
Контекст — это объект, который используется для хранения состояния между вызовами блока интеграции.
Контекст особенно полезен для управления состоянием между вызовами API. Он может использоваться для передачи данных о предыдущих шагах выполнения (например, переменные состояния), хранения данных, необходимых для выполнения операции на каждом шаге, а также для работы с пагинацией.
В блоках интеграции контекст используется для:
- Сохранения состояния между вызовами
- Передачи информации между страницами пагинации
- Хранения данных, которые могут быть использованы в следующих шагах или запросах
Например, в блоках с пагинацией контекст часто содержит информацию о текущей странице, которая может быть использована для получения следующей страницы данных. В блоках без пагинации контекст может использоваться для хранения информации о состоянии выполнения операции.
Использование контекста в блоках с пагинацией
В интеграциях с пагинацией контекст часто используется для управления состоянием между вызовами API. Например, блок может быть настроен для выполнения нескольких запросов к API с постраничной навигацией, и контекст может содержать информацию о текущей странице, количестве записей или другие параметры, которые нужны для продолжения работы на следующем шаге.
Пример использования контекста для управления пагинацией:
var state;
if (context === undefined) {
state = 1; // Начинаем с первой страницы
} else {
state = context + 1; // Переходим на следующую страницу
}
var hasNext = state < limit; // Проверяем, есть ли следующая страница
Где:
state
— это текущая страница, которая хранится в контекстеhasNext
— это проверка, которая указывает нужно ли делать еще один запрос для следующей страницы
Контекст передается как часть аргументов в функцию executePagination
.
В зависимости от реализации, контекст может быть использован для хранения данных между вызовами и передаваться обратно в функцию для обработки в следующем шаге.
Пример:
executePagination: (z, bundle, context) => {
// Логика работы с контекстом и данных API
}
Где context
— это объект, который может быть использован для хранения состояния, такого как номер текущей страницы, данные для обработки или другие переменные.
Возвращаемое состояние и контекст
Контекст может быть возвращен из функции executePagination
для использования в будущих вызовах. Когда в интеграции используется пагинация, обычно возвращается информация о текущем состоянии, например, номер страницы или другие переменные.
Пример возвращаемого состояния:
return {
output: data,
output_variables: [...],
state: { currentPage: nextPage }, // Возвращаемое состояние, содержащее данные о текущем шаге
hasNext: hasNext // Информация, есть ли еще страницы для загрузки
};
Где state
может содержать информацию о текущем шаге (например, номер текущей страницы), которая передается в следующий вызов.
Если состояние между вызовами сохранять не требуется, можно передавать пустой state
:
{
output: [normalizeComment],
output_variables: [...],
state: {}, // Пустой объект, так как пагинация или состояния между запросами не требуются
hasNext: false
}
Была ли статья полезна?