- При вызове методов, доступных в REST API v3, метод автоматически выводит предупреждение.
Обзор
Когда нужно обработать большие объёмы данных из list-методов REST API версии 2 по частям (чанками), используйте FetchListV2.make().
Метод реализует быстрый алгоритм итерации по большим наборам данных без загрузки всех данных в память сразу. Каждая итерация возвращает следующую страницу/пакет результатов, пока не получены все данные.
// Базовое использование
import { EnumCrmEntityTypeId } from '@bitrix24/b24jssdk'
const generator = $b24.actions.v2.fetchList.make({
method: 'crm.item.list',
params: {
entityTypeId: EnumCrmEntityTypeId.deal,
filter: { '>opportunity': 10000 }
},
idKey: 'id',
customKeyForResult: 'items',
requestId: 'unique-request-id'
})
for await (const chunk of generator) {
// Обработка чанка (например, сохранение в БД, анализ и т.д.)
console.log(`Processing ${chunk.length} items`)
}
Когда использовать FetchListV2.make()
- Очень большие объёмы данных: когда число записей в тысячах или десятках тысяч.
- Потоковая обработка: когда данные нужно обрабатывать по мере поступления.
- Длительные операции: когда обработка каждой записи требует значительного времени.
Сигнатура метода
make<T = unknown>(
options: ActionFetchListV2
): AsyncGenerator<T[]>
Параметры
Объект options содержит следующие свойства:
Возвращаемое значение
AsyncGenerator<T[]> — асинхронный генератор, возвращающий чанки данных в виде массивов типа T.
Каждая итерация генератора возвращает:
- Массив элементов (чанк) до
50записей. - Генератор завершается, когда все данные получены.
Ключевые понятия
Автоматическое предупреждение
При вызове методов, которые доступны в REST API версии 3, система автоматически выводит предупреждение:
"The method {method_name} is available in restApi:v3. It's worth migrating to the new API."
Это указывает на то, что стоит рассмотреть миграцию на более новую версию REST API.
AsyncGenerator vs Promise
В отличие от CallListV2.make(), который возвращает Promise со всеми данными сразу, FetchListV2.make() возвращает асинхронный генератор:
Оптимизация производительности
Метод реализует рекомендованный Bitrix24 алгоритм для эффективной работы с большими объёмами данных:
start: -1: отключает подсчёт общего числа записей, значительно ускоряет выполнение запроса.- Фильтрация по возрастающему id: каждый следующий запрос использует фильтр
>cursorIdKeyс id последнего полученного элемента (читается черезidKey). - Потоковая обработка: данные обрабатываются по мере поступления, экономя память.
- Автоматическое определение конца данных: запросы останавливаются при получении пустого массива или если число элементов меньше размера страницы (
50).
Структура ответа REST API v2
В REST API версии 2 разные методы могут возвращать данные в разных структурах:
- Прямой массив:
{ result: [...] } - Сгруппированный массив:
{ result: { items: [...] } }
Параметр customKeyForResult позволяет указать ключ, по которому расположены данные в ответе.
Ограничения
- Размер страницы: фиксированное ограничение Bitrix24 REST API версии 2 —
50записей на запрос. - Сортировка фиксирована: метод всегда сортирует по
cursorIdKey(по умолчанию равенidKey) по возрастанию, потому что курсорная пагинация опирается на фильтр>cursorIdKeyдля прохождения по набору. Пользовательское значениеorderнарушило бы этот инвариант, поэтому сигнатура типа исключаетorder, а любое значение, переданное в runtime, отбрасывается с записьюwarningв лог. Для сужения выборки используйтеfilter. - Только для list-методов: предназначен только для методов, возвращающих массивы данных.
Обработка ошибок
Поскольку метод возвращает асинхронный генератор, ошибки обрабатываются иначе, чем в CallListV2.make():
import { SdkError } from '@bitrix24/b24jssdk'
try {
const generator = $b24.actions.v2.fetchList.make({
method: 'some.method',
params: { /* some_params */ },
idKey: 'id',
customKeyForResult: 'items',
requestId: 'unique-request-id'
})
for await (const chunk of generator) {
// Обработка чанка (например, сохранение в БД, анализ и т.д.)
console.log(`Processing ${chunk.length} items`)
}
} catch (error) {
// Обработка ошибки
if (
error instanceof SdkError
&& error.code === 'JSSDK_CORE_B24_FETCH_LIST_METHOD_API_V2'
) {
console.error(`${error.message}`, { code: error.code })
} else {
console.error('Some error', error)
}
}
Примеры
Поэтапная обработка большого числа компаний
import { B24Hook, EnumCrmEntityTypeId, LoggerFactory, Text, SdkError, AjaxError } from '@bitrix24/b24jssdk'
type Company = {
id: number
title: string
}
const devMode = !!(typeof import.meta !== 'undefined' && (import.meta.dev || import.meta.env?.DEV))
const $logger = LoggerFactory.createForBrowser('Example:ProcessCrmItems', devMode)
const $b24 = B24Hook.fromWebhookUrl('https://your_domain.bitrix24.com/rest/1/webhook_code/')
async function processCrmItemList(): Promise<void> {
let batchNumber = 0
let totalItems = 0
const sixMonthAgo = new Date()
sixMonthAgo.setMonth((new Date()).getMonth() - 6)
sixMonthAgo.setHours(0, 0, 0)
const requestId = 'some-crm-item-list'
try {
const generator = $b24.actions.v2.fetchList.make<Company>({
method: 'crm.item.list',
params: {
entityTypeId: EnumCrmEntityTypeId.company,
filter: {
// фильтрация по названию
'=%title': 'Prime%',
'>=createdTime': Text.toB24Format(sixMonthAgo) // созданы как минимум 6 месяцев назад
},
select: ['id', 'title']
},
idKey: 'id',
customKeyForResult: 'items',
requestId
})
for await (const chunk of generator) {
batchNumber++
totalItems += chunk.length
$logger.info(`Processing batch #${batchNumber}`, {
batchSize: chunk.length,
totalSoFar: totalItems
})
// Пример: сохранение в базу данных
await saveToDatabase(chunk)
// Пример: отправка в очередь сообщений
await sendToMessageQueue(chunk)
}
$logger.notice(`Processed ${totalItems} elements in ${batchNumber} batches`)
} catch (error) {
if (error instanceof SdkError) {
$logger.error(`Processing error: ${error.message}`, {
code: error.code,
batchNumber,
totalItems
})
} else {
$logger.error('Unknown error', { error, batchNumber, totalItems })
}
throw error
}
}
// Вспомогательные функции
// Реализация сохранения в базу данных
async function saveToDatabase(items: Company[]): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 100)) // Simulation
}
// Реализация отправки в очередь сообщений
async function sendToMessageQueue(items: Company[]): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 50)) // Simulation
}
// Использование
try {
await processCrmItemList()
} catch (error) {
$logger.critical('A problem occurred', { error })
}
Пагинация tasks.task.list (поле запроса ≠ поле ответа)
tasks.task.list сортирует и фильтрует по ID (верхний регистр), но возвращает каждую задачу с id в нижнем регистре. Задайте idKey на поле ответа, а cursorIdKey — на поле запроса: курсор тогда читает последний id со страницы и запрашивает следующий с >ID:
type TaskListItem = { id: string, title: string }
const generator = $b24.actions.v2.fetchList.make<TaskListItem>({
method: 'tasks.task.list',
params: {
filter: { RESPONSIBLE_ID: 1 }, // поля фильтра задач в верхнем регистре
select: ['ID', 'TITLE'] // выбираем в верхнем регистре, но в ответе id / title в нижнем
},
idKey: 'id', // читаем task.id из ответа
cursorIdKey: 'ID', // order + постраничный фильтр ">ID" в запросе
customKeyForResult: 'tasks'
})
let total = 0
for await (const chunk of generator) {
total += chunk.length
}
console.log(`Processed ${total} tasks`)
Без cursorIdKey значение idKey: 'ID' по умолчанию невозможно прочитать из ответа в нижнем регистре, поэтому пагинация остановится после первых 50 задач — и SDK залогирует warning, указывающий сюда.
Альтернативы и рекомендации
- Размер чанка: Bitrix24 REST API версии 2 всегда возвращает до 50 записей на запрос.
- Оптимальная параллельность: при обработке данных из генератора рекомендуется ограниченная параллельность (3–5 одновременных операций).
- Обработка ошибок: всегда обрабатывайте ошибки внутри цикла
for await...of, чтобы предотвратить прерывание всего процесса. - Мониторинг прогресса: внедряйте логирование прогресса для длительных операций.
- Для последовательных запросов: используйте
Callдля одиночных вызовов. - Для пакетных операций: используйте
Batchдля выполнения до 50 команд в одном запросе. - На стороне клиента (браузер): используйте встроенный объект
B24Frame. - См. также: Фильтрация — построение
filter(и почемуorderотбрасывается).