
在nestjs世界裡,幾乎所有東西都是Component,像是Service, Repository, Factory, Helper ...,然後透過constructor可以注入到各個Component或Controller。在上一章節我們實作了Controller,但如我之前提到的,Controller只需要負責處理HTTP請求即可,商業邏輯、資料處理就交給Services,盡可能做到單一職責,程式要朝著符合SOLID原則去開發。
接下來的程式,寫過Angular的朋友應該會覺得有些地方蠻類似的,很有親切感。
cd src/modules/Users & mkdir Services
export class CreateUserDTO {
    readonly _id: number;
    readonly _name: string;
    readonly _age: number;
}
import { Component } from '@nestjs/common';
import { HttpException } from '@nestjs/core';
import { Observable } from 'rxjs/Observable';
import { CreateUserDTO } from '../DTO/create-users.dto';
//別忘記Component裝飾器
@Component()
export class UsersService {
    //假資料
    private users = [
        { "_id": 1, "_name": "Michael", "_age": 25 },
        { "_id": 2, "_name": "Mary", "_age": 27 }
    ];
    //使用Promise,盡可能避免使用callback方式。
    getAllUsers() {
        return Promise.resolve(this.users);
    }
    getUser(id: number) {
        const user = this.users.find((user) => {
            return user._id === id;
        });
        if (!user) {
            //nestjs對於http exception有API可以調用,建議使用。
            throw new HttpException("user not found", 404);
        }
        return Promise.resolve(user);
    }
    //在nestjs也是可以歡樂使用Rx.js
    addUser(user: CreateUserDTO): Observable<object[]> {
        this.users.push(user);
        return Observable.of(this.users);
    }
}
import { Module } from '@nestjs/common';
import { UsersController } from './Users/users.controller';
import { UsersService } from './Users/Services/users.service';
@Module({
  modules: [],
  controllers: [UsersController],
  components: [UsersService],
})
export class ApplicationModule { }
import { Controller, Get, Post, Request, Response, Param, Next, HttpStatus, Body } from '@nestjs/common';
import { CreateUserDTO } from './DTO/create-users.dto';
import { UsersService } from '../Users/Services/users.service';
@Controller('users')
export class UsersController {
    //依賴注入,建議要使用,這是低耦合作法
    constructor(private userService: UsersService) { }
    @Get()
    //使用Express的參數
    getAllUsers( @Request() req, @Response() res, @Next() next) {
        //Promise 有then catch方法可以調用
        this.userService.getAllUsers()
            .then((users) => {
                //多種Http的Status可以使用
                res.status(HttpStatus.OK).json(users);
            })
            .catch((error) => {
                console.error(error);
                res.status(HttpStatus.INTERNAL_SERVER_ERROR);
            })
    }
    @Get('/:id')
    //使用Express的參數
    //@Param('id')可以直接抓id參數
    getUser( @Response() res, @Param('id') id) {
        //+id ,+符號可以直接把string 轉換成number
        this.userService.getUser(+id)
            .then((user) => {
                res.status(HttpStatus.OK).json(user);
            })
            .catch((error) => {
                console.error(error);
                res.status(HttpStatus.INTERNAL_SERVER_ERROR);
            })
    }
    @Post()
    addUser( @Response() res, @Body() createUserDTO:CreateUserDTO) {
        //使用Rx.js,所以回傳可以做更多資料流的處理
        this.userService.addUser(createUserDTO).subscribe((users) => {
            res.status(HttpStatus.OK).json(users);
        });
    }
}
接著使用Postman
 
成功取得資料。
 
成功取得資料。
 
成功新增一筆資料
到目前為止都很順利,nestjs不單單有Rx.js可以使用,還可以寫async/await,我們改寫一下UsersController,程式如下。
src/modules/Users/users.controller.ts
import { Controller, Get, Post, Request, Response, Param, Next, HttpStatus, Body } from '@nestjs/common';
import { CreateUserDTO } from './DTO/create-users.dto';
import { UsersService } from '../Users/Services/users.service';
@Controller('users')
export class UsersController {
   //依賴注入,建議要使用,這是低耦合作法
   constructor(private userService: UsersService) { }
   @Get()
   //使用Express的參數
   async getAllUsers( @Request() req, @Response() res, @Next() next) {
       //Promise 有then catch方法可以調用
       await this.userService.getAllUsers()
           .then((users) => {
               //多種Http的Status可以使用
               res.status(HttpStatus.OK).json(users);
           })
           .catch((error) => {
               console.error(error);
               res.status(HttpStatus.INTERNAL_SERVER_ERROR);
           })
   }
   @Get('/:id')
   //使用Express的參數
   //@Param('id')可以直接抓id參數
   async getUser( @Response() res, @Param('id') id) {
       //+id ,+符號可以直接把string 轉換成number
       await this.userService.getUser(+id)
           .then((user) => {
               res.status(HttpStatus.OK).json(user);
           })
           .catch((error) => {
               console.error(error);
               res.status(HttpStatus.INTERNAL_SERVER_ERROR);
           })
   }
   @Post()
   async addUser( @Response() res, @Body() createUserDTO: CreateUserDTO) {
       //使用Rx.js,所以回傳可以做更多資料流的處理
       await this.userService.addUser(createUserDTO).subscribe((users) => {
           res.status(HttpStatus.OK).json(users);
       })
   }
}
再進行一下第六點的檢查,一切都正常顯示,大功告成,已經學會怎樣寫Service了。
程式碼在github