Обработка ошибок
Каждая ошибка, вызванная вашим middleware, будет поймана grammY. Для обработки ошибок следует установить собственный обработчик ошибок.
Самое главное, что этот раздел научит вас как ловить ошибки, которые могут быть получены.
После этого мы рассмотрим все три типа ошибок, с которыми может столкнуться ваш бот.
Название | Значение |
---|---|
Bot | Объект Error, который оборачивает любую ошибку, возникающую в вашем middleware (например, две ошибки ниже). |
Grammy | Выбрасывается, если API сервер возвращает ok: , указывая на то, что ваш запрос был недействительным и не прошел |
Http | Выбрасывается, если не удалось достичь API сервера |
Более продвинутый механизм обработки ошибок можно найти внизу.
Отлов ошибок
То, как вы будете отлавливать ошибки, зависит от ваших настроек.
Long Polling
Если вы запускаете бота через bot
или используете grammY runner, то вам следует установить обработчик ошибок через bot
.
В grammY по умолчанию установлен обработчик ошибок, который останавливает бота, если он был запущен с помощью bot
. Затем он перебрасывает ошибку. Что произойдет дальше, зависит от платформы. Поэтому вам следует установить обработчик ошибок через bot
.
Например:
bot.catch((err) => {
const ctx = err.ctx;
console.error(`Ошибка при обработке обновления ${ctx.update.update_id}:`);
const e = err.error;
if (e instanceof GrammyError) {
console.error("Ошибка в запросе:", e.description);
} else if (e instanceof HttpError) {
console.error("Не удалось связаться с Telegram:", e);
} else {
console.error("Неизвестная ошибка:", e);
}
});
2
3
4
5
6
7
8
9
10
11
12
Вебхуки
Если вы запускаете бота через вебхуки, grammY передаст ошибку в используемый вами веб-фреймворк, например, express
. Вы должны обрабатывать ошибки в соответствии с соглашениями этого фреймворка.
Объект BotError
Объект Bot
связывает полученную ошибку с соответствующим объектом контекста, который вызвал ее появление. Это работает следующим образом.
Какая бы ошибка ни возникла при обработке обновления, grammY перехватит ее для вас. Часто бывает полезно получить доступ к объекту контекста, который вызвал ошибку.
grammY никак не касается полученной ошибки, а вместо этого заворачивает ее в экземпляр Bot
. Учитывая, что этот объект имеет имя err
, вы можете получить доступ к исходной ошибке через err
. К соответствующему объекту контекста можно обратиться через err
.
Посмотрите класс Bot
в документации grammY API.
Объект GrammyError
Если метод API, например send
, не сработает, grammY выбросит Grammy
. Обратите внимание, что также экземпляры Grammy
будут обернуты в объекты Bot
, если они будут выброшены в middleware.
Полученный Grammy
указывает на то, что соответствующий API-запрос завершился неудачей. Ошибка предоставляет доступ к коду ошибки, возвращаемому бэкендом Telegram, а также к ее описанию.
Ознакомьтесь с классом Grammy
в документации grammY API.
Объект HttpError
При неудачном сетевом запросе возникает ошибка Http
. Это означает, что grammY не смог связаться с API сервером бота. Объект ошибки содержит информацию о том, почему запрос не удался, которая доступна в свойстве error
.
Вы редко увидите такую ошибку, если только ваша сетевая инфраструктура нестабильна или API сервер вашего бота временно не работает.
Обратите внимание, что если с сервером Bot API можно связаться, но он возвращает
ok:
для данного вызова метода, вместо него будет выброшенfalse Grammy
.Error
Посмотрите класс Http
в документации grammY API.
Границы ошибок
Это продвинутая тема, которая в основном полезна для больших ботов. Если вы относительно недавно знакомы с grammY, просто пропустите остаток этого раздела.
Если вы разделили свою кодовую базу на разные части, то границы ошибок позволят вам установить разные обработчики ошибок для разных частей middleware. Они достигают этого, позволяя вам оградить ошибки в части вашего middleware. Другими словами, если ошибка возникла в специально защищенной части middleware, она не сможет выйти за пределы этой части системы middleware. Вместо этого будет вызван специальный обработчик ошибок, а окруженная часть middleware сделает вид, что успешно завершила работу. Это особенность системы middleware grammY, поэтому границы ошибок не зависят от того, работаете ли вы с ботом с помощью вебхуков или long polling.
Как вариант, вы можете вместо этого позволить middleware выполнить возобновление после обработки ошибки, продолжая работу прямо за границей ошибки. В этом случае огражденный middleware не только ведет себя так, как будто оно успешно завершилось, но и передает поток управления следующему middleware, которое было установлено после границы ошибки. Таким образом, создается впечатление, что middleware, находящийся внутри границы ошибки, вызвал next
.
const bot = new Bot("");
bot.use(/* A */);
bot.use(/* B */);
const composer = new Composer();
composer.use(/* X */);
composer.use(/* Y */);
composer.use(/* Z */);
bot.errorBoundary(boundaryHandler /* , Q */).use(composer);
bot.use(/* C */);
bot.use(/* D */);
bot.catch(errorHandler);
function boundaryHandler(err: BotError, next: NextFunction) {
console.error("Ошибка в Q, X, Y, или Z!", err);
/*
* Вы можете вызвать `next`, если хотите запустить
* middleware на C в случае ошибки:
*/
// await next()
}
function errorHandler(err: BotError) {
console.error("Ошибка в A, B, C, или D!", err);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
В приведенном выше примере boundary
будет вызван для
- всех middleware, которые передаются в
bot
после.error Boundary boundary
(т.е.Handler Q
), и - всех middleware, установленных на последующих экземплярах composer (т.е.
X
,Y
иZ
).
Что касается пункта 2, вы можете перейти к расширенному объяснению middleware, чтобы узнать, как работает цепочка в grammY.
Вы также можете применить границу ошибки к Composer без вызова bot
:
const composer = new Composer();
const protected = composer.errorBoundary(boundaryHandler);
protected.use(/* B */);
bot.use(composer);
bot.use(/* C */);
bot.catch(errorHandler);
function boundaryHandler(err: BotError, next: NextFunction) {
console.error("Ошибка в B!", err);
}
function errorHandler(err: BotError) {
console.error("Ошибка в C!", err);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Обработчик boundary
из приведенного выше примера будет вызван для middleware, привязанных к protected
.
Если вы хотите, чтобы ошибка пересекала границу (то есть передавалась за ее пределы), вы можете повторно вызвать ошибку внутри своего обработчика ошибок. Тогда ошибка будет передана на следующую окружающую границу.
В некотором смысле, вы можете рассматривать обработчик ошибок, установленный через bot
, как самую внешнюю границу ошибки.