Как сделать так, чтобы пользовательская функция промежуточного программного обеспечения регистрировалась на консоли в режиме отладки Koa в TypeScript? - PullRequest
0 голосов
/ 03 февраля 2019

Использование Koa v2.7.0 и TypeScript v3.3.1

Моя функция промежуточного программного обеспечения "errorHandler" экспортируется следующим образом

export const clientErrorHandler = () => {
    return async (ctx: Context, next: NextFunction) => {
        try{
            await next();
        }
        catch (err){
            if(err instanceof HTTPClientError){
                console.warn(err);
                ctx.status = err.statusCode;
                ctx.body = err.message;
                ctx.app.emit('error', err, ctx);
           }
       }
   }
}

Моя логика, которая обрабатывает прикрепление промежуточного программного обеспечения к заданномуПриложение Koa выглядит следующим образом:

export const handleErrors = (app: Koa) => {
    const serverErrHandler = serverErrorHandler();
    serverErrHandler._name = 'serverErrorHandler';
    app.use(serverErrHandler)
}

Причина, по которой я пытаюсь создать это свойство, связана с документацией по Koa (см. Ссылку ниже), в которой говорится, что мы можем дать функциям промежуточного программного обеспечения свойство _name, чтобыкогда мы запускаем программу с установленным DEBUG=koa*, эта функция промежуточного программного обеспечения сможет иметь имя, которое отображается в консоли.

Поскольку JavaScript не позволяет определять имена функций во время выполнения, вы можететакже установите имя промежуточного программного обеспечения как ._name.Это полезно, когда у вас нет контроля над именем промежуточного программного обеспечения.Например:

const path = require('path'); const serve = require('koa-static');
const publicFiles = serve(path.join(__dirname, 'public'));
publicFiles._name = 'static /public';
app.use(publicFiles);

Источник приведенного выше фрагмента: https://github.com/koajs/koa/blob/master/docs/guide.md#debugging-koa

Однако при попытке этого, так как я использую TypeScript, онмне не нравится, что я пытаюсь установить свойство для этой анонимной функции.

[ts] Свойство '_name' не существует для типа '(ctx: Context, next: NextFunction) => Promise '.

Я надеялся найти лучший способ позволить себе добавить это маленькое свойство _name в эту анонимную функцию, чтобы у меня были надежные журналы отладки.

1 Ответ

0 голосов
/ 03 февраля 2019

Когда я писал это, я закончил тем, что нашел два возможных решения.

Единственное, что я собираюсь сделать, это просто не использовать анонимную функцию, поэтому нет необходимости изменять _name свойство на моей функции промежуточного программного обеспечения.Перечитав документацию по koa, я думаю, что ключевая фраза, которую я просмотрел, была

"для промежуточного программного обеспечения , которую вы не можете контролировать "

Мое определение функции промежуточного программного обеспечения теперь выглядит следующим образом:

export const clientErrorHandler = () => {
    let clientErrHandler = async (ctx: Context, next: NextFunction) => {
        try{
          await next();
        }
        catch (err){
            if(err instanceof HTTPClientError){
              console.warn(err);
              ctx.status = err.statusCode;
              ctx.body = err.message;
              ctx.app.emit('error', err, ctx);
            }
        }
      }
    return clientErrHandler;
}

Теперь, если бы это гипотетически было в случае, когда вы не имели контроля над именем функции промежуточного программного обеспечения стороннего производителя И вы использовали TypeScript, я обнаружил, чточто это решение по переполнению стека помогает в этом сценарии: https://stackoverflow.com/a/18640025

Используя это предложение по стеку, можно определить интерфейс и выполнить утверждение типа с помощью анонимной функции, чтобы получить результат, который позволил бы набрать код для машинописного текста.установите свойство _name в возвращаемой функции, не жалуясь, что такого свойства не существует.

Просто чтобы продемонстрировать, как это выглядит:

Даже при том, что я демонстрирую это в коде, который вытехнически не было бы доступа к модификации Я предполагаю, что вы могли бы также сделать утверждение типа на стороне вызывающей стороныl, а затем измените свойство _name после этого.

interface MiddlewareFunction { (ctx: Context, next: NextFunction ): Promise<void>; _name: string; }

export const serverErrorHandler = () => {
  return <MiddlewareFunction> async function (ctx: Context, next: NextFunction){
    try {
      await next();
    }
    catch (err) {
      if(process.env.NODE_ENV === 'production'){
        ctx.status = 500;
        ctx.body = 'Internal Server Error';
      }
      else {
        ctx.status = err.status;
        ctx.body = err.stack;
        ctx.app.emit('error', err, ctx);
      }
    }
  }
}

Тот же код, что и в вопросе:

export const handleErrors = (app: Koa) => {
    const serverErrHandler = serverErrorHandler();
    serverErrHandler._name = 'serverErrorHandler';
    app.use(serverErrHandler)
}

EDIT : Вы также можете просто изменитьиз функции стрелки обратно в нормальную именованную функцию javascript в возвращении.

export const serverErrorHandler = () => {
  return async function serverErrorHandler (ctx: Context, next: NextFunction){
    try {
      await next();
    }
    catch (err) {
      if(process.env.NODE_ENV === 'production'){
        ctx.status = 500;
        ctx.body = 'Internal Server Error';
      }
      else {
        ctx.status = err.status;
        ctx.body = err.stack;
        ctx.app.emit('error', err, ctx);
      }
    }
  }
}
...