Рецепт: подписка на события Pull

Открыть живой канал из frame-приложения Bitrix24 и реагировать на push-события через useB24Helper + Pull-клиент.
Мы всё ещё дорабатываем эту страницу. Некоторых данных здесь может не хватать — скоро дополним.

Цель

Frame-приложение, которое получает обновления в реальном времени от Bitrix24 — например, счётчик-бейдж растёт, когда приходит новое сообщение в чате или меняется ответственный по делу CRM. Pull-клиент мультиплексирует транспорты WebSocket и long-polling; вы видите только один callback.

Стек и предпосылки

  • Vue 3 + Vite (или Nuxt), работающие внутри placement Bitrix24
  • @bitrix24/b24jssdk@^1.0.0
  • На портале должен быть включён модуль Pull (он есть на каждом облаке и большинстве коробочных инсталляций)
pnpm add @bitrix24/b24jssdk

Полный пример

src/components/PullPanel.vue:

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import {
  initializeB24Frame,
  LoadDataType,
  LoggerFactory,
  useB24Helper,
  type B24Frame,
  type TypePullMessage
} from '@bitrix24/b24jssdk'

const logger = LoggerFactory.createForBrowser('PullPanel', import.meta.env.DEV)
const events = ref<Array<{ at: string, command: string }>>([])
let $b24: B24Frame | null = null

const {
  initB24Helper,
  destroyB24Helper,
  usePullClient,
  useSubscribePullClient,
  startPullClient
} = useB24Helper()

function handleEvent(message: TypePullMessage) {
  logger.info('pull', message)
  events.value.unshift({
    at: new Date().toLocaleTimeString(),
    command: message.command
  })
  // Держим видимый лог коротким.
  if (events.value.length > 20) events.value.length = 20
}

onMounted(async () => {
  $b24 = await initializeB24Frame()

  // App + Profile нужны, чтобы хелпер мог зарегистрировать Pull-канал.
  await initB24Helper(
    $b24,
    [LoadDataType.App, LoadDataType.Profile],
    'pull-panel-init'
  )

  usePullClient()
  // Слушаем события модуля `crm`. Используйте `'application'` (по умолчанию) для
  // собственных событий вашего приложения.
  useSubscribePullClient(handleEvent, 'crm')
  startPullClient()
})

onBeforeUnmount(() => {
  destroyB24Helper()
  $b24 = null
})
</script>

<template>
  <section>
    <h2>Live events</h2>
    <ul v-if="events.length">
      <li v-for="(event, index) in events" :key="index">
        <code>{{ event.at }}</code> — {{ event.command }}
      </li>
    </ul>
    <p v-else>Waiting for events…</p>
  </section>
</template>

Запуск

Откройте приложение внутри Bitrix24, затем вызовите событие CRM в другой вкладке — перетащите сделку на новую стадию, добавьте дело, смените ответственного. В течение секунды команда события (например, crm_deal_update) появляется вверху списка. Компонент держит видимыми последние 20 событий.

Как это работает

  • useB24Helper() возвращает замыкание над одним экземпляром B24HelperManager. Это не Vue composable — он не читает хуки жизненного цикла Vue. Вы сами подключаете его в onMounted / onBeforeUnmount.
  • initB24Helper($b24, dataTypes, requestId) загружает данные, нужные Pull-клиенту для регистрации канала. Без LoadDataType.App и LoadDataType.Profile последующий вызов usePullClient() выбрасывает исключение.
  • usePullClient() создаёт транспорт Pull (WebSocket с фолбэком на long-polling). useSubscribePullClient(handler, moduleId) регистрирует ваш callback для этого модуля. startPullClient() собственно открывает соединение — вызывайте его последним.
  • destroyB24Helper() разрушает транспорт и снимает подписчиков. Вызов при размонтировании предотвращает утечку WebSocket при закрытии слайдера приложения.

Ограничения

  • Порядок обязан быть initB24HelperusePullClientuseSubscribePullClientstartPullClient. Вызов useSubscribePullClient до usePullClient выбрасывает PullClient is not initialized. Ошибка намеренная — она рано выявляет ошибки подключения.
  • useB24Helper() возвращает один общий экземпляр на замыкание. Если вы создадите второй useB24Helper() и снова вызовете initB24Helper, второй вызов переиспользует существующий менеджер, а не создаёт новый.
  • moduleId по умолчанию 'application'. Чтобы слушать модули портала ('crm', 'tasks', 'im', …), передавайте их явно. Подписка на несколько модулей требует нескольких вызовов useSubscribePullClient.
  • События Pull — best-effort. Они отлично подходят для «разбудить UI», но не для «это источник истины». Всегда перезапрашивайте через REST, когда действие пользователя зависит от свежести.

См. также