События и подписки
send — это запрос-ответ: ты вызываешь метод, хост отвечает событием Result или Failed. subscribe — поток входящих: всё, что хост присылает, включая ответы на чужие send.
import bridge from "@vkma.dev/bridge";
await bridge.send("VKWebAppInit");const user = await bridge.send("VKWebAppGetUserInfo");// user: UserInfo — id, first_name, photo_100, …Типы приходят из каталога @vkma.dev/bridge-schema: props берутся из RequestPropsMap, ответ — из ReceiveDataMap. Метод без ответной стороны в каталоге (например, VKWebAppLibverifyCheck) резолвится как Promise<void>.
Как парится ответ
Заголовок раздела «Как парится ответ»Каждый send получает request_id. По умолчанию инстанс инъектирует его сам — __vkma_1, __vkma_2, … Когда хост присылает событие с request_id, для которого есть ожидание:
request_idвырезается из полезной нагрузки — промис резолвится телом без него;- событие с
error_typeреджектит промис этим же телом (тоже безrequest_id).
Передай свой request_id в props, если он нужен для логики на стороне хоста — политика инстанса явный идентификатор не трогает:
await bridge.send("VKWebAppGetUserInfo", { request_id: "sync-1" });Ответ без request_id (или с чужим) — это событие, а не ответ: промисы не трогаются.
Реджект — не Error, а тело Failed-события. Дискриминируй по error_type:
import type { ErrorData } from "@vkma.dev/bridge";
try { await bridge.send("VKWebAppGetUserInfo");} catch (failed) { const data = failed as ErrorData; switch (data.error_type) { case "client_error": // data.error_data.error_reason break; case "api_error": // data.error_data.error_msg, error_code break; case "auth_error": // data.error_data.error_reason break; }}Если ответ не пришёл вообще, промис висит вечно — навеси timeout или signal.
subscribe
Заголовок раздела «subscribe»Каждое входящее событие, включая ответы на send. Формат — event.detail.type / event.detail.data, данные приходят как есть, с request_id:
const off = bridge.subscribe(event => { switch (event.detail.type) { case "VKWebAppUpdateConfig": // event.detail.data.appearance: "light" | "dark" break; case "VKWebAppLocationChanged": // event.detail.data.location: string break; }});
off(); // отпискаsubscribe возвращает функцию отписки; есть и классический bridge.unsubscribe(listener). Хендлер может отписываться прямо внутри вызова.
Что чем обрабатывать
Заголовок раздела «Что чем обрабатывать»- Нужен ответ —
send:VKWebAppGetUserInfo,VKWebAppStorageGet,VKWebAppShowWallPostBox(промис резолвится, когда пользователь закрыл бокс). - Хост сообщает сам —
subscribe:VKWebAppUpdateConfig,VKWebAppLocationChanged,VKWebAppAudioPaused,VKWebAppUpdateInsets.
Ответ на чужой send тоже приедет в subscribe — если пишешь общий обработчик, отфильтруй полезные нагрузки с request_id.
Что происходит с каждым событием по пути, видно в tap — он пишет и запросы, и ответы, и события.