js 打字机_打字稿节点js express js创建后端应用程序

js 打字机

介绍(Introduction)

Hi there! At the end of this article you’ll know how to create a simple and reliable back-end application you can use as a sample for your future projects.

嗨,您好! 在本文的最后,您将知道如何创建一个简单而可靠的后端应用程序,可以将其用作将来项目的示例。

You can take a look at the code directly in its dedicated repository.To each step of this tutorial matches a specific commit.

您可以直接在其专用存储库中查看代码。本教程的每个步骤都与特定的提交相匹配。

要求 (Requirements)

npm install -g typescript

概要 (Summary)

  1. Project setup | Quick initialization, npm packages & program entry point

    项目设置| 快速初始化,npm软件包和程序入口点

  2. Routing setup | Controllers, routes & routers

    路由设置| 控制器,路由和路由器

  3. Error handling | Custom errors & error handling function

    错误处理自定义错误和错误处理功能

项目设置(Project setup)

初始化(Initialization)

Since your back-end application is going to use TypeScript, Node.js and Express.js, you need to install a few packages (also called dependencies).To do so, initialize your project using the npm init command :

由于您的后端应用程序将使用TypeScript,Node.js和Express.js,因此您需要安装一些软件包(也称为依赖项)。为此,请使用npm init命令初始化您的项目:

npm init -y

💬 This creates a package.json file that later will contain all the information about your project dependencies.

💬这将创建一个package.json文件,该文件以后将包含有关项目依赖项的所有信息。

Once it’s done, you need to indicate that your project is a TypeScript project.To do so, create a TS config file using the following tsc command :

完成后,您需要指出您的项目是TypeScript项目。为此,请使用以下tsc命令创建TS配置文件:

tsc --init

💬 This creates a tsconfig.json file that contains some default options I invite you to explore in its dedicated schema store.

💬这将创建一个tsconfig.json文件,其中包含一些默认选项,我邀请您在其专用模式存储中进行浏览

套餐概述 (Packages overview)

Almost every project depends on some external packages. These packages are considered to be the project’s dependencies.Some of them are always required by your project, but some others are only needed during development : these are called dev dependencies.

几乎每个项目都依赖于一些外部软件包。 这些软件包被认为是项目的依赖项。其中一些始终是您的项目所需要的,而另一些仅在开发期间才需要:这些被称为dev依赖项

Here are the packages you are about to install :

这是您将要安装的软件包:

📦 dotenv (dependency)
📦 express (dependency)
📦 @types/express (dev dependency)
📦 @types/node (dev dependency)
📦 nodemon (dev dependency)
📦 ts-node (dev dependency)
📦 typescript (dev dependency)

All of these packages have a specific purpose which I invite you to explore a little bit by clicking on each one of them to get a quick overview.

所有这些软件包都有特定的用途,我邀请您通过单击它们中的每一个来进行快速浏览以进行一些探索。

软件包安装 (Packages installation)

Let’s now install your dependencies using the npm install command :

现在,使用npm install命令安装依赖项

npm install dotenv express

💬 This does two things. On one hand, it installs both dotenv and express packages inside your project’s node_modules folder, and on the other registers them both inside your package.json dependencies.

does这有两件事。 一方面,它将dotenvexpress软件包都安装在项目的node_modules文件夹中,另一方面,将它们都注册在package.json依赖项中

Let’s continue by installing your dev dependencies using the same command :

让我们继续使用相同的命令安装dev依赖项

npm install -D @types/express @types/node nodemon ts-node typescript

💬 This does exactly the same thing than before except for the -D option that registers the packages inside your package.json dev dependencies.

💬除了将-D选项注册到package.json dev依赖项内的-D选项之外,这和以前完全一样。

环境变量 (Environment variables)

An application config is likely to vary between deploys, especially between developer workstations. For instance you may not want to make your server listening to the same port as your co-worker because yours is already in use.Because of that we have what we call environment variables (like the port).

部署之间,尤其是开发人员工作站之间,应用程序配置可能会有所不同。 例如,由于您的服务器已经在使用中,您可能不想让您的服务器侦听与您的同事相同的端口,因此我们有了所谓的环境变量(例如端口)。

They are all generally located in the same file, at the root of your application.This file is commonly called the .env file, and here’s the one you need :

它们通常都位于应用程序根目录下的同一文件中。此文件通常称为.env文件,这是您需要的文件:

NODE_ENV='dev'
APP_PORT=3000

💬 Here is located every single global & configurable variable of your project. You may want to add some in the future but that’ll be quite enough for now…

is这里是项目的每个全局和可配置变量。 您将来可能要添加一些,但是现在就足够了……

程序入口点 (Program entry point)

Well done, you’ve setup the whole project. Now you need a program entry point. Some code that lets you start your server and send it some requests.In order, follow these steps :

做得好,您已经设置了整个项目。 现在您需要一个程序入口点。 一些使您能够启动服务器并向其发送请求的代码。请按以下步骤操作:

  1. Create a src folder at the root of your project directory

    在项目目录的根目录下创建一个src文件夹

  2. Create an app.ts inside your src folder

    src文件夹中创建一个app.ts

  3. Take a look at and paste the following lines inside your app.ts file :

    查看一下并将以下行粘贴到app.ts文件中:

import dotenv from 'dotenv';
import express from 'express';


// load the environment variables from the .env file
dotenv.config({
  path: '.env'
});


/**
 * Express server application class.
 * @description Will later contain the routing system.
 */
class Server {
  public app = express();
}


// initialize server app
const server = new Server();


// make server listen on some port
((port = process.env.APP_PORT || 5000) => {
  server.app.listen(port, () => console.log(`> Listening on port ${port}`));
})();

启动脚本(Starting script)

To make your server app start, add the following lines inside your package.jsonfile :

为了使您的服务器应用启动,请在package.json文件内添加以下几行:

"scripts": {
    "dev": "nodemon src/app.ts"
}

Then open your command prompt and type this :

然后打开命令提示符并键入:

npm run dev

路由设置 (Routing setup)

控制器(Controllers)

A controller is a set of methods that were assembled by thematic and that are called by the server to respond to some specific client requests.One controller for one thematic.

控制器是由主题组装的一组方法,服务器调用这些方法以响应某些特定的客户端请求。 一个主题一个控制器。

路由和路由器 (Routes & routers)

Routing basically tells your server how to respond to client requests. But there can be many different client requests, so what do we have to do to make our server treat every one of them ? We create what we call routes and routers.

路由基本上告诉您的服务器如何响应客户端请求。 但是可能有许多不同的客户端请求,那么我们要怎么做才能使服务器处理每个请求? 我们创建所谓的路由路由器

A route is a link between the client request and the right controller method that needs to be called in response.

路由是客户端请求和需要作为响应而调用的正确控制器方法之间的链接。

A good practice is to split your routes by thematic. If your project is a website about animals then there’s a huge chance that you don’t mix up dogs & tigers. So there will be some specific routes for dogs and some others for tigers.And this is where routers come into play.

一个好的做法是按主题划分路线。 如果您的项目是有关动物的网站,那么您很有可能不会混淆狗和老虎。 因此,有一些针对狗的特定路线,还有针对老虎的其他路线,这就是路由器的作用所在。

A router can distinguish routes by thematic and execute the appropriate code for each one of them.

路由器可以按主题区分路由,并为每个路由执行适当的代码。

So you will have a router about dogs that will contain all the routes about dogs, and another about tigers that will contain all the routes about tigers. One router for one thematic.

因此,您将拥有一个关于狗的路由器,它将包含所有关于狗的路线,而另一个关于老虎的路由器将包含关于老虎的所有路线。 一台路由器即可进行一个专题讨论

实作 (Implementation)

The first step now is to start by creating the controllers. Remember : one controller for one thematic. Follow these steps :

现在的第一步是从创建控制器开始。 切记:一个主题的控制器。 按着这些次序 :

  1. Create a new folder named controllers inside your src folder

    src文件夹中创建一个名为controllers的新文件夹

  2. Chose two unique thematics (keep it simple, it’s just a sample)

    选择两个独特的主题(保持简单,这只是示例)
  3. Create two unique controllers in separate files inside your folder :

    在文件夹内的单独文件中创建两个唯一的控制器:
class ThemeAController {
  defaultMethod() {
    return {
      text: `You've reached the ${this.constructor.name} default method`
    };
  }
}


export = new ThemeAController();
class ThemeBController {
  defaultMethod() {
    return {
      text: `You've reached the ${this.constructor.name} default method`
    };
  }
}


export = new ThemeBController();

💬 Each controller owns the same default method that you will later call to respond to a specific client request, using a specific route in a specific router.

💬每个控制器拥有相同的默认方法,您稍后将使用特定路由器中的特定路由调用该方法来响应特定客户端请求。

Now you are going to implement your own routers. Remember: one router for one thematic, so one router for one controller thematic, so one router for one controller.

现在,您将实现自己的路由器。 请记住:一台路由器用于一个主题,所以一台路由器用于一个控制器主题,所以一台路由器用于一个控制器。

  1. Create a new folder named routers in your src folder

    src文件夹中创建一个名为routers的新文件夹

  2. Create as many sub-folders inside routers as there are thematics

    routers内创建与主题相同的子文件夹

  3. Create your routers inside their matching folder, following this structure :

    按照以下结构在其匹配文件夹中创建路由器:
import { NextFunction, Request, Response, Router } from 'express';
import ThemeAController from '../../controllers/ThemeAController';


class ThemeARouter {
  private _router = Router();
  private _controller = ThemeAController;


  get router() {
    return this._router;
  }


  constructor() {
    this._configure();
  }


  /**
   * Connect routes to their matching controller endpoints.
   */
  private _configure() {
    this._router.get('/', (req: Request, res: Response, next: NextFunction) => {
      res.status(200).json(this._controller.defaultMethod());
    });
  }
}


export = new ThemeARouter().router;

💬 Each router is configured as soon as it is constructed. The _configure() method centralizes all the routes that match your router’s thematic and give them all a specific controller method that is called when the route’s endpoint is reached.

💬每台路由器一经构建即被配置。 _configure()方法集中所有与您的路由器主题匹配的路由,并为它们提供所有特定的控制器方法,这些方法将在到达路由端点时被调用。

Now you need a main router that detects which thematic is concerned by the client request, and to which router it must pass it.

现在,您需要一个主路由器,用于检测客户端请求所涉及的主题,以及必须将其传递给哪个路由器。

  1. Create a MasterRouter.ts file inside your routers folder

    routers文件夹内创建一个MasterRouter.ts文件

  2. Copy/paste the following code inside your file :

    在文件内复制/粘贴以下代码:
import { Router } from 'express';
import ThemeARouter from './themeA/ThemeARouter';
import ThemeBRouter from './themeB/ThemeBRouter';


class MasterRouter {
  private _router = Router();
  private _subrouterA = ThemeARouter;
  private _subrouterB = ThemeBRouter;


  get router() {
    return this._router;
  }


  constructor() {
    this._configure();
  }


  /**
   * Connect routes to their matching routers.
   */
  private _configure() {
    this._router.use('/themeA', this._subrouterA);
    this._router.use('/themeB', this._subrouterB);
  }
}


export = new MasterRouter().router;

3. Edit your program entry point (app.ts file) :

3.编辑程序入口点( app.ts文件):

import MasterRouter from './routers/MasterRouter';


// ...


/**
 * Express server application class.
 * @description Will later contain the routing system.
 */
class Server {
  public app = express();
  public router = MasterRouter;
}


// initialize server app
const server = new Server();


// make server app handle any route starting with '/api'
server.app.use('/api', server.router);


// ...

Now start your server using npm run dev and try to reach the following :

现在使用npm run dev启动服务器,并尝试达到以下目标:

http://localhost:{port}/api/themeA
http://localhost:{port}/api/themeB

The output should either be :

输出应该是:

{"text": "You've reached the ThemeAController default method"}
---- or
{
"text": "You've reached the ThemeBController default method"}

Congrats! 🤙 You’ve setup your back-end application (in its simpliest form).

恭喜! 🤙您已经设置了后端应用程序(以最简单的形式)。

错误处理 (Error handling)

Suppose you have a front-end application that uses your back-end app’s API.You may want to inform your front-end app in case something went wrong inside your back-end app, so its final user can be informed too…

假设您有一个使用后端应用程序API的前端应用程序。您可能想通知您的前端应用程序,以防后端应用程序内部出现问题,因此也可以通知最终用户……

To do so, you have to create your custom error handling system, as well as your custom error objects.Fortunately JavaScript has its own Error object, so all you have to do is to extend this object and add all the props you need.

为此,您必须创建自定义错误处理系统以及自定义错误对象。幸运的是,JavaScript具有自己的Error对象,因此您所要做的就是扩展该对象并添加所需的所有道具。

  1. Create a new folder named models inside your src folder

    src文件夹中创建一个名为models的新文件夹

  2. Create a ErrorHandler.ts file and copy/paste the following code inside :

    创建一个ErrorHandler.ts文件并复制/粘贴以下代码:

export default class ErrorHandler extends Error {
  constructor(
    public statusCode: number,
    public message: string
  ) {
    super();
  }
}

3. Also edit your app.ts :

3.同时编辑您的app.ts

import express, { Request, Response, NextFunction } from 'express';
// ...
import ErrorHandler from './models/ErrorHandler';


// ...


// make server app handle any route starting with '/api'
server.app.use('/api', server.router);


// make server app handle any error
server.app.use((err: ErrorHandler, req: Request, res: Response, next: NextFunction) => {
  res.status(err.statusCode || 500).json({
    status: 'error',
    statusCode: err.statusCode,
    message: err.message
  });
});


// ...

4. Now go may want to see how this works. Go to one of your controllers and replace it by the following code :

4.现在,可能要查看它的工作原理。 转到您的一个控制器,并将其替换为以下代码:

import ErrorHandler from '../models/ErrorHandler';


class ThemeAController {
  defaultMethod() {
    throw new ErrorHandler(501, 'Not implemented method');
  }
}


export = new ThemeAController();

5. Finally go to its matching router and replace its _configure() method by the following code :

5.最后,转到其匹配的路由器,并用以下代码替换其_configure()方法:

// ...


/**
 * Connect routes to their matching controller endpoints.
 */
private _configure() {
  this._router.get('/', (req: Request, res: Response, next: NextFunction) => {
    try {
      const result = this._controller.defaultMethod();
      res.status(200).json(result);
    }
    catch (error) {
      next(error);
    }
  });
}


// ...

💬 In case any error is thrown from the controller in the try block, it is immediatly caught and redirected to the next application middleware, in this specific case : the code that you’ve just written in your app.ts file and that handles your application errors.

💬如果在try块中从控制器抛出了任何错误,则会立即捕获该错误并将其重定向到下一个应用程序中间件,在这种特定情况下:您刚刚在app.ts文件中编写并处理您的代码应用程序错误。

Start your server and try to reach the endpoint where you’ve placed an error.The output should be the same as this one :

启动服务器并尝试到达已放置错误的端点。输出应与此相同:

{"status": "error","statusCode": 501,"message": "Not implemented method"}

DONE! 🥳 Here’s your back-end application sample, built with TypeScript, Node.js/Express.js. If you have any question please feel free to ask !

完成! 🥳这是使用TypeScript Node.js / Express.js构建的后端应用程序示例。 如果您有任何疑问,请随时提问!

Special thanks to Chinedu Orie with his article about error handling in Express.

特别感谢Chinedu Orie撰写的有关Express中错误处理的文章

翻译自: https://medium.com/@pierre.viara/typescript-node-js-express-js-create-a-backend-application-f5110dbe5c19

js 打字机

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值