Маршрутизатор Express v4 как класс

#node.js #typescript #express

#node.js #машинописный текст #экспресс

Вопрос:

Приложение компилируется без ошибок и сообщает, что сервер запускается с правильного порта. Однако, когда я перехожу к любому из моих зарегистрированных маршрутов, я получаю сообщение об ошибке «не удается получить доступ к этому маршруту».

Я не нашел много информации о Express с классами, особенно о части маршрутизатора. Из console.log(controller.router) переменной маршрутизатора это кажется правильным, путь, отсутствующий в нем, странный, но я предполагаю, что регулярное выражение просто занимает место вместо этого.

В this.router экземпляре также нет метода path, поэтому я не уверен, как еще указать путь, отличный от get(path, handler) .

 console.log(`/v1${controller.basePath}`, controller.router):

""""
/v1/users [Function: router] {
  params: {},
  _params: [],
  caseSensitive: undefined,
  mergeParams: undefined,
  strict: undefined,
  stack: [
    Layer {
      handle: [Function: bound dispatch],
      name: 'bound dispatch',
      params: undefined,
      path: undefined,
      keys: [],
      regexp: /^/users/?$/i,
      route: [Route]
    },
    Layer {
      handle: [Function: bound dispatch],
      name: 'bound dispatch',
      params: undefined,
      path: undefined,
      keys: [],
      regexp: /^/users/?$/i,
      route: [Route]
    },
    Layer {
      handle: [Function: bound dispatch],
      name: 'bound dispatch',
      params: undefined,
      path: undefined,
      keys: [Array],
      regexp: /^/users/(?:([^/] ?))/?$/i,
      route: [Route]
    },
    Layer {
      handle: [Function: bound dispatch],
      name: 'bound dispatch',
      params: undefined,
      path: undefined,
      keys: [Array],
      regexp: /^/users/(?:([^/] ?))/?$/i,
      route: [Route]
    }
  ]
}
"""
  

Я также пробовал с localhost:1337/v1/users/ just incase, но происходит то же самое.

Я не понимаю, что может быть не так, заранее спасибо за помощь!

Класс приложения

 import * as express from "express"
import * as mongoose from "mongoose"
import * as bodyParser from "body-parser"

mongoose.connect("mongodb://localhost:27017/socketpro", {
    useUnifiedTopology: true,
    useNewUrlParser: true,
    useCreateIndex: true,
})

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

    private controllers: any

    constructor(controllers: any, port: number) {
        this.port = port
        this.controllers = controllers
        this.app = express()

        this.initializeMiddlewares()
        this.initializeControllers()
    }

    private initializeMiddlewares() {
        this.app.use(bodyParser.json())
    }

    private initializeControllers() {
        this.controllers.forEach((controller: any) => {
            console.log(`/v1${controller.basePath}`, controller.router)
            this.app.use(`/v1${controller.basePath}`, controller.router)
        })
    }

    public listen() {
        this.app.listen(this.port, () => {
            console.log(`App listening on the port ${this.port}`)
        })
    }
}

export default App
  

Пользовательский контроллер

 import { UserModel as User, UserInterface } from "../Utils/User"
import { Router, Request, Response } from "express"

export default class UsersController {
    [x: string]: any

    public basePath = "/users"
    public router: Router = null

    private posts: UserInterface[] = []

    constructor() {
        this.router = Router()
        this.intializeRoutes()
    }

    public intializeRoutes() {
        let routes = [
            {
                path: "/",
                method: "get",
                function: "GetUsers",
            },
            {
                path: "/",
                method: "post",
                function: "CreateUser",
            },
            {
                path: "/:id",
                method: "get",
                function: "GetUser",
            },
            {
                path: "/:id",
                method: "post",
                function: "UpdateUser",
            },
        ]

        routes.map((route) => {
            let path = `${this.basePath}${route.path ?? ""}`

            switch (route.method) {
                case "get":
                    this.router.get(path, this[route.function])
                    break
                case "post":
                    this.router.post(path, this[route.function])
                    break
            }
        })
    }

    async GetUser(request: Request, response: Response) {
        let userId: string = request.params.id

        let user = await User.findOne({
            _id: userId,
        })

        response.send({
            user,
        })
    }

    async GetUsers(request: Request, response: Response) {
        response.send({status: true})
    }

    async CreateUser(request: Request, response: Response) {
        let user: UserInterface = new User(request.body)

        user = await user.save()

        response.send(user)
    }

    async UpdateUser(request: Request, response: Response) {
        let body: UserInterface = request.body

        await User.updateOne(
            {
                _id: request.params.id,
            },
            body
        ).exec()

        response.send({
            status: true,
        })
    }
}
  

Репозиторий кода:https://github.com/Rusherz/express-router-class

Отображается URL-адрес Chrome: localhost: 1337 / v1 / users и ошибка: не удается ПОЛУЧИТЬ / v1 /users

Комментарии:

1. Непонятно, о чем вы спрашиваете. Можете ли вы показать нам свой код и описать конкретную проблему с вашим кодом? Код, необходимый для понимания вопроса, ДОЛЖЕН быть вставлен в сам вопрос, а не доступен только как внешняя ссылка. Это рекомендации stackoverflow, и существует целая куча веских причин, по которым требуется, чтобы вопросы были написаны таким образом. Пожалуйста, включите соответствующий код для вопроса В сам вопрос, отформатированный соответствующим образом как код. Вы можете оставить внешнюю ссылку на остальную часть репозитория, но это не должно быть единственной ссылкой на код.

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

3. Вы создаете объект Router и добавляете к нему маршруты, но что вам делать app.use(path, router) с объектом router, чтобы фактически подключить маршрутизатор к вашему серверу?

4. К вашему сведению, указание имен функций маршрута с помощью строки в вашей таблице немного странно. Почему бы просто напрямую не ссылаться на сами методы?

5. Замечание. Вы создали свою собственную абстракцию для многих вещей, которые выполняет Express, и в процессе очень затруднили понимание вашего кода тем, кто знаком с Express. Я не уверен, что вы делаете что-то проще, просто создавая свой собственный внутренний API, который больше никто не узнает. Вы могли бы использовать интерфейс express и расширить его, а не скрывать / заменять, чтобы добавить свои собственные возможности (если чего-то не хватает), и тогда это не показалось бы чуждым разработчику Express.

Ответ №1:

Проблема с моим кодом заключалась в области видимости, или в том, что я считаю областью видимости.

Я нашел сообщение, на котором основывал это,https://dev.to/aligoren/developing-an-express-application-using-typescript-3b1

Проблема с кодом заключается в файлах контроллера, у меня был

 async GetUser(request: Request, response: Response) {
    let userId: string = request.params.id

    let user = await User.findOne({
        _id: userId,
    })

    response.send({
        user,
    })
}
  

Вместо:

 GetUser = async (request: Request, response: Response) => {
    let userId: string = request.params.id

    let user = await User.findOne({
        _id: userId,
    })

    response.send({
        user,
    })
}
  

Другим решением было бы изменить:

 switch (route.method) {
    case "get":
        this.router.get(path, this[route.function])
        break
    case "post":
        this.router.post(path, this[route.function])
        break
}
  

Для:

 switch (route.method) {
    case "get":
        this.router.get(path, this[route.function].bind(this))
        break
    case "post":
        this.router.post(path, this[route.function].bind(this))
        break
}
  

Просто на случай, если у кого-то возникнет похожая проблема со мной в будущем.