node.js:在app.js

时间:2017-06-22 21:22:03

标签: node.js typescript repository-pattern service-layer

我正在使用node.js和typescript开发一个应用程序。我按照本文中概述的方法http://brianflove.com/2016/11/08/typescript-2-express-node/构建了我的server.ts文件,这是server.ts文件的示例代码:

import * as bodyParser from "body-parser";
import * as cookieParser from "cookie-parser";
import * as express from "express";
import * as logger from "morgan";
import * as path from "path";
import errorHandler = require("errorhandler");
import methodOverride = require("method-override");

/**
 * The server.
 *
 * @class Server
 */
export class Server {

    public app: express.Application;

    /**
     * Bootstrap the application.
     *
     * @class Server
     * @method bootstrap
     * @static
     * @return {ng.auto.IInjectorService} Returns the newly created injector for this app.
     */
    public static bootstrap(): Server {
        return new Server();
    }

    /**
     * Constructor.
     *
     * @class Server
     * @constructor
     */
    constructor() {
        //create expressjs application
        this.app = express();

        //configure application
        this.config();

        //add routes
        this.routes();

        //add api
        this.api();
    }

    /**
     * Create REST API routes
     *
     * @class Server
     * @method api
     */
    public api() {
        //empty for now
    }

    /**
     * Configure application
     *
     * @class Server
     * @method config
     */
    public config() {
        //empty for now
    }

    /**
     * Create router
     *
     * @class Server
     * @method api
     */
    public routes() {
        //empty for now
    }
}

以下是routes函数的示例代码:

/**
  * Create router.
  *
  * @class Server
  * @method config
  * @return void
  */
private routes() {
  let router: express.Router;
  router = express.Router();
  //let mymodel = this.connection.model<IMyModel>("MyModel", MySchema);
  //let myservice: MyService = new MyService(this.myRepository(mymodel));


  //IndexRoute
  IndexRoute.create(router, myservice);

  //use router middleware
  this.app.use(router);
}

对于我的特定情况,我正在向路由中注入服务以执行可能需要执行的相应操作。如果我以这种方式将服务注入控制器,这是我的担忧。这是否意味着每个提出请求的人都会收到不同的服务和存储库或同一个实例?理想情况下,我认为如果每个用户收到不同的实例会更好。这将如何影响在存储库层中进行的数据库调用?我是node.js的新手,我仍然试图绕过app.js,server.js和请求之间的关系,因为node.js是单线程的。

1 个答案:

答案 0 :(得分:0)

  

这是否意味着每个发出请求的人都会收到不同的服务和存储库或同一个实例

在您的示例中,所有请求都将使用MyService的相同实例。

只要您确保依赖关系图中的类是无状态的,这不是一个大问题。

  

我认为如果每个用户收到不同的实例会更好。

我同意你的看法。我更喜欢每个请求一个实例的想法。

  

这会影响在存储库层中进行的数据库调用吗?

正如我所说,只要你不在请求之间共享状态就不应该是一个问题。某些数据库建议使用一个唯一的永久连接(例如节点)在这种情况下,将单个存储库作为单例共享是一个好主意。

app.js,server.js

之间的关系

server.js是我们创建并开始运行一个或多个应用的​​文件。每个应用程序通常在不同的VHOST或PORT上运行。

  

并且作为node.js发出的请求是单线程的

Node.js使用非阻塞模型。当您向数据库发送查询时,Node.js将继续处理其他请求。这意味着查询不会阻止主线程。当查询返回时,主线程将选择事件并继续执行请求。

另一种方法

我创建了一个库,可以让您更好地控制依赖项和范围的注入。例如,您不需要执行以下操作:

let mymodel = this.connection.model<IMyModel>("MyModel", MySchema);
let myservice: MyService = new MyService(this.myRepository(mymodel));

除此之外,您可以声明要注入的类及其依赖项:

@injectable()
class MyService() {

    @inject("IMyModel") private mymodel: IMyModel;

    // ...
}

此外,不是声明路线,而是:

IndexRoute.create(router, myservice);

您可以使用像@Get

这样的装饰器
@injectable()
class MyService() {

    @inject("IMyModel") private mymodel: IMyModel;

    @Get("/someURL")
    public async get() {
        return await this.mymodel.readAll();
    }

}

最后,要控制生命周期,您只需要使用不同类型的绑定。

所有请求共享一个实例:

container.bind<MyService>("MyService").to(MyService).inSingletonScope();

每个请求的新实例:

container.bind<MyService>("MyService").to(MyService).inTransientScope();

以下是具有HTTP GET enpoint的控制器的真实示例:

import { Controller, Get } from "inversify-express-utils";
import { injectable } from "inversify";
import { Repository } from "@lib/universal/interfaces/infra";
import { Aircraft } from "@lib/universal/interfaces/aviation";
import { authorize } from "@lib/server/auth/auth_middleware";
import { referenceDataPaths } from "@stellwagen/universal/config/app_paths";
import { FEATURE } from "@lib/server/constants/privileges";
import { aircraftRepository } from "../ioc_module/decorators";

@injectable()
@Controller(
    referenceDataPaths.server.aircraft.name,
    authorize({ feature: FEATURE.APP_ACCESS_REFERENCE_DATA })
)
class AircraftController {

    @aircraftRepository private readonly _aircraftRepository: Repository<Aircraft>;

    @Get(referenceDataPaths.server.aircraft.endpoints.get)
    public async get() {
        return await this._aircraftRepository.readAll();
    }

}

export { AircraftController };

图书馆为inversify-express-utils,由InversifyJS提供支持。