Типичная batch / cron-задача: экспорт компаний в CSV одним вебхуком. Не превышает лимиты частоты и использует fetchList, поэтому память не растёт независимо от размера набора данных.
Структура проекта
my-export-job/
├── dist/
├── src/
│ └── process-company-list.ts
├── out/ # сгенерированные *.csv файлы
├── .env.local # B24_HOOK=...
├── package.json
└── tsconfig.json
package.json
{
"name": "my-export-job",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node --env-file=.env.local dist/process-company-list.js"
},
"devDependencies": {
"@types/node": "^22",
"typescript": "^5.6"
},
"dependencies": {
"@bitrix24/b24jssdk": "latest",
"chalk": "^5"
}
}
src/process-company-list.ts
// @check-ignore: node:fs not available in docs typecheck context
import { writeFileSync } from 'node:fs'
import {
B24Hook,
EnumCrmEntityTypeId,
LoggerFactory,
Text,
type ISODate
} from '@bitrix24/b24jssdk'
const $logger = LoggerFactory.createForBrowser('export', process.env.NODE_ENV === 'development')
if (!process.env.B24_HOOK) {
$logger.error('B24_HOOK is not set in .env.local')
process.exit(1)
}
const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
$logger.info(`Portal: ${$b24.getTargetOrigin()}`)
type Company = { id: number, title: string, createdTime: ISODate }
async function main() {
const generator = $b24.actions.v2.fetchList.make<Company>({
method: 'crm.item.list',
params: {
entityTypeId: EnumCrmEntityTypeId.company,
select: ['id', 'title', 'createdTime']
},
idKey: 'id',
requestId: 'export:companies'
})
const rows: string[] = ['id,title,createdTime']
for await (const chunk of generator) {
for (const c of chunk) {
rows.push([
c.id,
JSON.stringify(c.title ?? ''),
Text.toDateTime(c.createdTime).toFormat('yyyy-LL-dd HH:mm:ss')
].join(','))
}
$logger.info(`Loaded ${chunk.length} (total ${rows.length - 1})`)
}
const out = `out/companies-${Date.now()}.csv`
writeFileSync(out, rows.join('\n'), 'utf8')
$logger.notice(`Wrote ${out}`)
$b24.destroy()
}
main().catch((error) => {
$logger.error('export failed', { error })
process.exit(1)
})
Почему fetchList?
- Память не растёт: каждая итерация
for awaitотдаёт чанк из 50 элементов, поэтому набор в 50 000 строк никогда не материализуется в RAM. - Встроенная пагинация: не пишите свой цикл
start: nextStart. - Аккуратно обрабатывает rate / operating лимитеры SDK между страницами.
Для полноценных массовых операций (удалить-затем-создать, массовые импорты) сочетайте экспорт с actions.v2.batchByChunk.
Полный исходник
Мастер установки
Многошаговый процесс установки, который создаёт пользовательские поля, регистрирует placement-ы, финализирует установку и празднует конфетти.
Аналитика CRM
Стримит все сделки через actions.v2.fetchList.make, группирует по стадиям, печатает отчёт по воронке (количество, конверсия %, средний чек, win rate).