Обзор
Используйте BatchV3.make() для выполнения до 50 команд REST API в одном запросе. Это особенно полезно, когда нужно получить или обновить большие объёмы данных, минимизируя сетевые запросы и соблюдая ограничения REST API.
// Базовое использование
import { EnumCrmEntityTypeId } from '@bitrix24/b24jssdk'
const response = await $b24.actions.v3.batch.make({
calls: [
['tasks.task.get', { id: 1 }],
['tasks.task.get', { id: 2 }]
],
options: {
isHaltOnError: true,
returnAjaxResult: true,
requestId: 'unique-request-id'
}
})
Сигнатура метода
make<T = unknown>(
options: ActionBatchV3
): Promise<CallBatchResult<T>>
Параметры
Объект options содержит следующие свойства:
Форматы команд (options.calls)
1. Массив кортежей (BatchCommandsArrayUniversal)
// @check-ignore: partial snippet — calls array literal, not a valid statement
calls: [
['method1', params1],
['method2', params2],
// ...
]
2. Массив объектов (BatchCommandsObjectUniversal)
// @check-ignore: partial snippet — object array literal, not a valid statement
calls: [
{ method: 'method1', params: params1 },
{ method: 'method2', params: params2 },
// ...
]
3. Объект с именованными командами (BatchNamedCommandsUniversal)
calls: {
command1: { method: 'method1', params: params1 },
command2: ['method2', params2],
// ...
}
Опции пакетного запроса (options.options)
Возвращаемое значение
Promise<CallBatchResult<T>> — promise, разрешающийся в объект CallBatchResult<T>.
Структура результата зависит от формата входных данных:
- Для массива команд: массив результатов в том же порядке.
- Для именованных команд: объект с ключами, соответствующими именам команд.
Данные элемента результата
Каждый result отдельной команды возвращается ровно так, как его отдал REST API,
включая null, когда вызываемый метод действительно не возвращает данных.
При типизации generic для методов, которые могут вернуть null, объявляйте его как
T | null.
null приводился к {}, что ломало nullable-type-guards на
стороне вызова (см. issue #23).Ограничения
Батч restApi:v3 — всё или ничего:
- Ошибки отдельных команд не возвращаются. Если любая команда в батче упадёт, весь батч провалится, и
response.getErrorMessages()верхнего уровня будет содержать ошибку(и);getData()вернёт пустую map. timeна каждомAjaxResult— это время уровня батча, не отдельной команды. Ограничитель частоты не относит длительность батча к отдельным методам.- Если в успешном v3-ответе отсутствует запись результата для какой-то команды (что указывает
на некорректный ответ API), SDK бросает
JSSDK_INTERACTION_BATCH_STRATEGY_V3_EMPTY_COMMAND_RESPONSE.
Передача данных между командами ($ref / $refArray)
Батч v3 может подать вывод одной команды во params последующей. Дайте команде-источнику алиас as, затем сошлитесь на него маркером $ref (одно значение) или $refArray (поле, собранное по items[] источника). Подстановку выполняет сервер — SDK лишь пробрасывает маркер. Используйте хелпер BatchRefV3 для сборки маркеров (он валидирует путь на стороне клиента):
import { BatchRefV3 as R } from '@bitrix24/b24jssdk'
const response = await $b24.actions.v3.batch.make({
calls: [
{ method: 'tasks.task.list', as: 'tasks', params: { select: ['id'] } },
{
method: 'tasks.task.list',
// сервер разворачивает это в `['id', 'in', [<id, собранные из tasks.items>]]`
params: { select: ['id', 'title'], filter: [['id', 'in', R.refArray('tasks.id')]] }
}
]
})
R.ref('alias.path.to.field')→{ $ref: '…' }— одно значение. В контекст попадают толькоitem(get) иitems(list/tail);add→ id /update→ bool — нет.R.refArray('alias.field')→{ $refArray: '…' }— собираетfieldпоitems[]алиаса. Путь должен содержать точку.- Некорректный путь или неразрешённая ссылка проваливают батч с
BITRIX_REST_V3_EXCEPTION_INVALIDSELECTEXCEPTION. - Только v3. Эти маркеры не подставляются в v2-батче
(
actions.v2.batch.make) — там они становятся литеральными значениями фильтра и молча дают неверный/пустой результат.
Обработка ошибок
SDK больше не проверяет методы батча по клиентскому списку v3: каждая команда отправляется на v3-batch-endpoint, и сервер валидирует каждую. Команда, называющая не-v3-метод, возвращается как серверная ошибка для этой команды (и, по семантике v3-батча, ошибка прерывает батч). Используйте BatchV2.make(), если батч содержит legacy-методы, или разделите смешанные батчи по версиям API.
Для успешных запросов всегда проверяйте isSuccess и обрабатывайте ошибки:
// @check-ignore: top-level return in error-handling illustration
const response = await $b24.actions.v3.batch.make({
calls: [
{ method: 'tasks.task.get', params: { id: 1 } },
{ method: 'tasks.task.get', params: { id: 2 } }
],
options: {
isHaltOnError: true,
returnAjaxResult: true,
requestId: 'unique-request-id'
}
})
if (!response.isSuccess) {
// Обработка ошибки
console.error(new Error(`Error: ${response.getErrorMessages().join('; ')}`))
return
}
// Работа с успешным результатом
const data = response.getData()
Примеры
Получение нескольких задач
// @check-ignore: full example — processResult callback and BatchCommands tuple inference not in scope
import type { AjaxResult, Result } from '@bitrix24/b24jssdk'
import { AjaxError, B24Hook, LoggerFactory, SdkError } from '@bitrix24/b24jssdk'
type TaskItem = {
id: number
title: string
}
const devMode = !!(typeof import.meta !== 'undefined' && (import.meta.dev || import.meta.env?.DEV))
const $logger = LoggerFactory.createForBrowser('Example:batchTasks', devMode)
const $b24 = B24Hook.fromWebhookUrl('https://your_domain.bitrix24.com/rest/1/webhook_code/')
async function getMultipleItems(itemIds: number[], requestId: string): Promise<TaskItem[]> {
if (itemIds.length < 1 || itemIds.length > 50) {
throw new SdkError({
code: 'MY_APP_GET_PROBLEM',
description: `The number of elements must be between 1 and 50`,
status: 404
})
}
const calls = itemIds.map(id => [
'tasks.task.get',
{
id,
select: ['id', 'title']
}
])
const response = await $b24.actions.v3.batch.make<{ item: TaskItem }>({
calls,
options: {
isHaltOnError: true,
returnAjaxResult: true,
requestId
}
})
if (!response.isSuccess) {
throw new Error(`Problem: ${response.getErrorMessages().join('; ')}`)
}
const resultData = (response as Result<AjaxResult<{ item: TaskItem }>[]>).getData() ?? []
const results: TaskItem[] = []
resultData.forEach((resultRow) => {
if (resultRow.isSuccess) {
const item = resultRow.getData()?.result.item
if (item) {
results.push(item)
}
}
})
return results
}
// Использование
const requestId = 'batch/tasks.task.get'
try {
const itemIds = [1, 2, 3]
const items = await getMultipleItems(itemIds, requestId)
$logger.info(`Retrieved ${items.length} items`, {
expected: itemIds.length,
retrieved: items.length,
items: items.map(c => ({ id: c.id, title: c.title }))
})
} catch (error) {
if (error instanceof AjaxError) {
$logger.critical(error.message, { requestId, code: error.code })
} else {
$logger.alert('Problem', { requestId, error })
}
}
Альтернативы и рекомендации
- Для последовательных запросов: используйте
Callдля одиночных вызовов. - Для работы со списками: используйте
CallListдля получения больших объёмов данных. - Для поэтапной обработки: используйте
FetchListдля обработки данных по мере поступления. - Для запуска большего числа команд (более 50): используйте
BatchByChunk, который автоматически разбивает команды на чанки по 50. - На стороне клиента (браузер): используйте встроенный объект
B24Frame.