首页 > 解决方案 > Typescript ExpressJS - 将服务注入 REST API 控制器

问题描述

我正在尝试使用 Typescript 对我的 express rest API 使用 OOP 方法,并且在编写类时遇到问题。

这个想法是有一个 AuthController 类调用私有 AuthService 类来与数据库交互。但是,当我尝试使用 AuthController 类调用 AuthService 类时,它总是返回 undefined。

初始化我的快速应用程序并注册我的控制器的应用程序类:

class App {
  private app;
  private controllers: Controller[];
  constructor(controllers: Controller[]) {
    this.app = express();
    this.controllers = controllers;
    this.config();
    this.initializeRoutes();
    this.initializeErrorHandler();
  }

  config() {
    console.log("running config");
    this.app.use(cors());
    this.app.use(express.json());
    this.app.use(helmet());
  }

  public listen() {
    this.app.listen(3000);
  }

  initializeRoutes() {
    this.controllers.forEach((controller: any) => {
      this.app.use("/", controller.router);
    });
  }
  initializeErrorHandler() {
    this.app.use(errorMiddleware);
  }
}

(async () => {
  try {
    await connection(); //creates my database connection
  } catch (error) {
    console.log("Error while connecting to the database", error);
    return error;
  }
  const app = new App([new AuthController()]);
  app.listen();
})();

这是我的 AuthController 在我的调用中被初始化const app = new App([new AuthController()]);

export default class AuthController implements Controller {
  public path = "/api/auth";
  public router = Router();
  private authService: AuthService = new AuthService();

  constructor() {
    this.initializeRoutes();
  }

  public initializeRoutes() {
    //login route
    this.router.post(this.path.concat("/login"), this.login);
    this.router.post(
      this.path.concat("/register"),
      validationMiddleware(CreateUserDto),
      this.register
    );
    this.router.post(this.path.concat("/resetpassword"), this.resetPassword);
    this.router.post(this.path.concat("/newpassword"), this.newPassword);
  }

  public async register(req: Request, res: Response, next: NextFunction) {
    const userData: CreateUserDto = req.body;
    try {
      let {
        tokens: { xAuthToken, xRefreshToken },
        user,
      } = await this.authService.register(userData);
      res.setHeader("x-auth-token", xAuthToken);
      res.setHeader("x-refresh-token", xRefreshToken);
      res.json(user);
    } catch (e) {
      next(e);
    }
  }
}

最后是 AuthService 类

export class AuthService {
  private userRepo: Repository<User> = getRepository(User);

  constructor() {}

  public async register(userData: CreateUserDto) {
    let foundUser = await this.userRepo.findOne({
      where: { email: userData.email.toLowerCase() },
    });
    console.log(foundUser);
    if (foundUser) {
      throw new EmailInUseException();
    } else {
      console.log(foundUser);
      const user = new User();
      user.email = userData.email.toLowerCase();
      user.password = userData.password;
      await this.userRepo.save(user);
      const tokens = this.createTokens(user);
      return {
        tokens,
        user,
      };
    }
  }
}

每当我从 AuthController 调用 AuthService 时,我都会收到“错误无法读取未定义的属性 'authService'”。

我尝试更改代码以直接初始化 AuthServiceconst app = new App([new AuthController(new AuthService()]);但这并不能解决问题。

任何帮助表示赞赏!

标签: javascriptnode.jstypescriptexpress

解决方案


发现问题。'this' 上下文正在改变。我将我的“注册”方法切换为解决问题的箭头函数

原来的:

class AuthController{


  public async register(req: Request, res: Response, next: NextFunction) {
    const userData: CreateUserDto = req.body;
    try {
      let {
        tokens: { xAuthToken, xRefreshToken },
        user,
      } = await this.authService.register(userData);
      res.setHeader("x-auth-token", xAuthToken);
      res.setHeader("x-refresh-token", xRefreshToken);
      res.json(user);
    } catch (e) {
      next(e);
    }
  }

}

新的:

class AuthController{


public register = async (req: Request, res: Response, next: NextFunction) => {
    const userData: CreateUserDto = req.body;
    try {
      let {
        tokens: { xAuthToken, xRefreshToken },
        user,
      } = await this.authService.register(userData);
      res.setHeader("x-auth-token", xAuthToken);
      res.setHeader("x-refresh-token", xRefreshToken);
      res.json(user);
    } catch (e) {
      next(e);
    }
  };
}

推荐阅读