TypeScript и Koa 2: Проблема async / await с глобальным обработчиком ошибок
Я пишу приложение с TypeScript, а также Koa 2.
Однако проблема, с которой я сталкиваюсь, заключается в том, что мой глобальный обработчик ошибок Koa не ловит ошибки, которые были брошены в моем приложении.
Возьмем, например, следующее промежуточное ПО (это самое первое промежуточное ПО перед загрузкой любых маршрутов):
app.use(async(ctx, next) => {
console.log("ErrorHandler loaded...");
try {
console.log("Trying for error...");
await next();
} catch (err) {
console.log("Caught error...");
ctx.status = err.status || 500;
ctx.response.body = "Error: " + err.message;
}
});
При обращении к моим маршрутам я вижу, что обработчик ошибок загружен и что блок try
выполняется.
Однако, если я брошу ошибку в маршрут (независимо от того, использую ли я throw
или ctx.throw
), все, что я получаю, - это сообщение об ошибке по умолчанию "не найдено" - так что любые ошибки, которые я бросаю, никогда не будут пойманы, и, следовательно, мой обработчик ошибок не будет обрабатывать его.
Теперь рассмотрим следующий транспилированный JavaScript:
app.use((ctx, next) => __awaiter(this, void 0, void 0, function* () {
console.log("ErrorHandler loaded...");
try {
console.log("Trying for error...");
yield next();
}
catch (err) {
console.log("Caught error...");
ctx.status = err.status || 500;
ctx.response.body = "Error: " + err.message;
}
}));
Вопрос двоякий:
- мое приложение не может поймать брошенные ошибки из-за транспиляции? Я имею в виду, будет ли это работать, если транспилированный JavaScript будет использовать
async
иawait
ключевые слова, а не транспонировать его в генераторы с использованиемyield
? - Если вышеизложенное верно: есть ли способ написать приложения Koa 2 с помощью TypeScript теперь ?
Edit
Я нашел "решение", чтобы заставить мои ошибки бросать, но я все еще не понимаю, почему Коа не поймал их.Этот цикл for of
повторяет массив контроллеров, которые я динамически загружаю. Для каждого контроллера я прилагаю соответствующий метод (действие.метод) класса (действие.цель) к маршруту (действие.маршрут) с использованием указанного http глагола (action.тип).
Однако я также связываю контекст с методом, чтобы гарантировать, что, согласно конвенциям Koa, this
связан с Context
:
for (let action of actionMetadata) {
router[action.type.toLowerCase()](action.route, (ctx, next) => {
(new action.target)[action.method].bind(ctx)(ctx, next);
});
}
Вышеизложенное вызывает проблему, при которой ошибки не перехвачены.
Для сравнения, приведенный ниже код работает: ошибки теперь ловятся Koa. Но это означает, что this
теперь уже не является Context
.
Я могу жить с этим, так как Context
это первый парам в моих маршрутах, но я не понимаю, почему ошибка не поймана, так как все промежуточное программное обеспечение, следующее за обработчиком ошибок (который является моим самым первым промежуточным программным обеспечением) , должно работать в его блоке try
:
for (let action of actionMetadata) {
router[action.type.toLowerCase()](action.route, (new action.target )[action.method]);
}
1 ответ:
Верно, похоже, что это была чистая ошибка пользователя, не гарантирующая, что каждое промежуточное ПО возвращает обещание (или является асинхронной функцией).
async
в следующем-это все, чего не хватало:for (let action of actionMetadata) { router[action.type.toLowerCase()](action.route, async (ctx, next) => { (new action.target)[action.method].bind(ctx)(ctx, next); }); }