BatchV3.make

Метод для выполнения пакетных запросов к REST API Bitrix24 версии 3. Позволяет выполнить до 50 команд в одном API-вызове.

Обзор

Используйте 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 содержит следующие свойства:

ПараметрТипОбязательныйОписание
callsBatchCommandsArrayUniversal | BatchCommandsObjectUniversal | BatchNamedCommandsUniversalДаКоманды для выполнения в батче. Поддерживает несколько форматов.
optionsIB24BatchOptionsНетДополнительные опции для выполнения пакетного запроса.

Форматы команд (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)

ОпцияТипПо умолчаниюОписание
isHaltOnErrorbooleantrueОстанавливать ли выполнение при первой ошибке.
returnAjaxResultbooleanfalseВозвращать ли объект AjaxResult вместо данных.
requestIdstringУникальный идентификатор запроса для отслеживания. Используется для дедупликации запросов и отладки.

Возвращаемое значение

Promise<CallBatchResult<T>> — promise, разрешающийся в объект CallBatchResult<T>.

Структура результата зависит от формата входных данных:

  • Для массива команд: массив результатов в том же порядке.
  • Для именованных команд: объект с ключами, соответствующими именам команд.

Данные элемента результата

Каждый result отдельной команды возвращается ровно так, как его отдал REST API, включая null, когда вызываемый метод действительно не возвращает данных. При типизации generic для методов, которые могут вернуть null, объявляйте его как T | null.

До v1.1.1 результат 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

BatchTasks.ts
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.