在 NodeJS TypeScript OOP

发布时间:2021-02-25 08:43

我正在尝试引入 cls-rtracer,但在实例化它时,它是未定义的。

代码是用 TypeScript 编写的,使用面向对象的范式而不是函数式。

在 NPM 中发布的库示例是功能性的。

我已将它即将到来的地方评论为未定义。

在这个 express 应用中引入任何其他中间件似乎很简单,除了 cls-rtracer

这是代码:

import express, {NextFunction, Response, Request} from 'express';
import * as bodyParser from 'body-parser';
import helmet from 'helmet';
import morgan from 'morgan';
import cors from 'cors';
import swaggerJSDoc from 'swagger-jsdoc';
import swaggerui from 'swagger-ui-express';
import {Controller} from './api/v1/controllers/Controller';
import {logger} from './api/v1/utils/Logger';
import {errorHandler} from './api/v1/utils/ErrorHandler';
import {BaseError} from './api/v1/utils/BaseError';
import {HttpStatusCode} from './api/v1/constants/HttpStatusCode';
import rTracer from 'cls-rtracer';

export const stream = {
  write: (text: string) => {
    logger.info(text.replace(/\n$/, ''));
  },
};

const swaggerOptions = {
  swaggerDefinition: {
    info: {
      title: 'Backend',
      descriptions: 'Service',
      contact: {
        name: '',
      },
      servers: ['http://localhost:8080//api/v1/domain'],
      version: '1.0.1',
    },
  },
  apis: ['./api/v1/routes/*.ts'],
};

const swaggerDocs = swaggerJSDoc(swaggerOptions);

export class App {
  public app: express.Application;
  public port: number;

  constructor(controllers: Controller[], port: number) {
    this.app = express();
    this.port = port;
    this.initializeMiddlewares();
    this.initializeHealth();
    this.initializeControllers(controllers);
    this.initializeErrorHandler();
    this.initializeSwagger();
  }

  private initializeMiddlewares() {
    this.app.use(rTracer.expressMiddleware());
    const requestId = rTracer.id();
    console.log(requestId); // giving undefined
    this.app.use(bodyParser.json());
    this.app.use(cors());
    this.app.use(
        morgan(
            [
              'ip: :remote-addr',
              ':method', ':url', 'HTTP/:http-version', 'status: :status',
              ':res[content-length]', 'referrer: :referrer',
              'userAgent: :user-agent', 'responseTime: :response-time ms',
            ].join(' | '),
            {stream: stream},
        ),
    );
    this.app.use(express.json());
    this.app.use(helmet());
  }

  private initializeControllers(controllers: Controller[]) {
    controllers.forEach((controller) => {
      this.app.use('/', controller.router);
    });
  }

  private initializeErrorHandler() {
    this.app.use(async (req: Request, res: Response, next: NextFunction) => {
      const error = new BaseError('Not Found', HttpStatusCode.NOT_FOUND, true, 'Not Found');
      next(error);
    });
    this.app.use(async (error: Error, req: Request, res: Response, next: NextFunction) => {
      if (!errorHandler.isTrustedError(error)) {
        // @ts-ignore: Unreachable code error
        res.status(error.status).json(error);
      }
      await errorHandler.handleError(error);
      // @ts-ignore: Unreachable code error
      res.status(error.httpCode || HttpStatusCode.INTERNAL_SERVER).json({error: error});
    });
  }

  private initializeSwagger() {
    this.app.use(
        '/api-docs',
        swaggerui.serve,
        swaggerui.setup(swaggerDocs, {explorer: true}),
    );
  }

  private initializeHealth() { }

  public listen() {
    this.app.listen(this.port, () => {
      logger.info(`listening on the port ${this.port}`);
    });
  }
}

export default App;

为什么它在下面的代码中完美运行:

import express from 'express';
import {CONFIG} from './config';
import MasterRouter from './routers/MasterRouter';
import ErrorHandler from './utils/ErrorHandler';
import rTracer from 'cls-rtracer';
import morgan from 'morgan';

class Server {
  public app = express();
  public router = MasterRouter;

  constructor(
  ) {
    this.correlationalIdMiddleware();
    this.loggingMiddleware();
    this.routingMiddleware();
    this.errorHandlingMiddleWare();
  }

  correlationalIdMiddleware() {
    this.app.use(rTracer.expressMiddleware());
  }

  loggingMiddleware() {
    this.app.use(morgan((tokens, req, res) => {
      const requestId = rTracer.id();
      return [
        `> requestId: ${requestId} -`,
        tokens.method(req, res),
        tokens.url(req, res),
        tokens.status(req, res),
        tokens.res(req, res, 'content-length'), '-',
        tokens['response-time'](req, res), 'ms',
      ].join(' ');
    }));
  }

  routingMiddleware() {
    this.app.use('/api', this.router);
  }

  errorHandlingMiddleWare() {
    this.app.use((req, res, next) => {
      const error = new ErrorHandler(404, 'Not Found');
      next(error);
    });
    this.app.use((error: ErrorHandler, req: any, res: any, next: any) => {
      const errorObject = {
        status: 'error',
        statusCode: error.statusCode,
        message: error.message,
      };
      const requestId = rTracer.id();
      console.log(`> requestId: ${requestId} - ${JSON.stringify(errorObject)}`);
      res.status(error.statusCode || 500).json(errorObject);
    });
  }
}

const server = new Server;

server.app.listen(CONFIG.PORT, () => {
  console.log(`> Server listening on ${CONFIG.PORT}`);
});
回答1