JavaScript >> Javascript 文檔 >  >> Node.js

NestJS 服務簡介

服務

在企業應用中,我們遵循 SOLID 原則,其中 S 代表 Single Responsibility。

控制器負責接受來自客戶端的 HTTP 請求並提供響應。為了提供響應,您可能需要連接到一些外部數據源。

如果我們在內部添加連接外部源的代碼,我們就沒有遵循單一責任原則。

為避免此問題,您使用服務,該服務將負責提供一些數據,這些數據可以在整個應用程序中重複使用。它還可以保存一些驗證邏輯或驗證用戶的邏輯。

創建和使用服務

在 NestJS 中可以創建兩種類型的服務:

  • 基於類的提供者
  • 非基於類的提供者

注意:如果你來自 Angular,你很有可能已經知道這些概念。

基於類的提供者

要創建基於類的提供程序,我們可以使用下面的 CLI 命令,該命令將在產品文件夾中創建服務。

nest generate service product

在產品文件夾中,你會發現兩個文件:

  • product.service.ts (為了邏輯。)
  • product.service.spec.ts (用於單元測試。)

您最終可能會為一項功能使用多種服務,甚至可能使用多種類型的提供商。

使用基於類的提供者

現在打開 product.service.ts 文件並添加以下代碼,我們將從 ProductController 中移動一些代碼 到 ProductService .

import { Injectable } from '@nestjs/common';
@Injectable()
export class ProductService {
    products = [
        { id: 1, name: 'One Plus 7', price: 48000 },
        { id: 2, name: 'I Phone X', price: 64999 }
    ];
    getProducts() {
        return this.products;
    }
    addProduct(product:any){
        this.products.push(product);
    }
    getProductById(id:number) {
        return this.products.find(p => p.id === id);
    }
}

現在服務已經準備好了,打開 product.controller.ts 並進行以下更改。

import { ProductService } from './product.service';
@Controller('product')
export class ProductController {
    constructor(private productService: ProductService) {}
    @Get()
    GetProducts() {
        return this.productService.getProducts();
    }
    @Post()
    AddProduct(@Req() req: Request, @Res() res: Response) {
        this.productService.addProduct(req.body);
        // return json data with default status code
        return res.json({ id: req.body.id });
        // to update the status code
        //return res.status(205).json({ id: req.body.id})
    }
    @Get(':id')
    GetProductById(@Param() param: any) {
        return this.productService.getProductById(+param.id);
    }
}

這裡使用 ProductService 的方式稱為依賴注入。

與 Controller 一樣,Services 也需要註冊,CLI 為我們完成了這項工作,您可以通過將其添加到模塊的 providers 數組中手動完成。

providers: [AppService, ProductService]

我們將在接下來的文章中介紹更多關於基於類的服務。

非基於類的提供者

我們還可以創建一個不是基於類的服務的服務。有兩種:

  • 令牌:我們可以使用字符串值作為令牌。
  • 工廠:當我們的服務需要來自其他服務的一些數據時很有用。

創建令牌

您可以創建一個注入令牌用作服務,為此,創建一個新文件 product.token.ts 在產品文件夾中並添加以下代碼:

export interface Product {
    endPoint: string;
}
export const PRODUCT = 'PRODUCT';
export const Product_Token : Product = {
    endPoint: 'http://localhost:3000/product'
}

現在打開 app.module.ts 並使用 providers 屬性註冊令牌。

import { PRODUCT, Product_Token } from './product/product.token';
providers: [
{
    provide : PRODUCT,
    useValue: Product_Token
}]

接下來,打開product.service.ts 讓我們使用這個令牌並添加以下代碼。這僅用於演示目的,在實時應用程序中我們可能希望使用此值。

import { Injectable, Inject } from '@nestjs/common';
import { PRODUCT, Product } from './product.token';
constructor(@Inject(PRODUCT) product: Product) 
{
    console.log(product.endPoint);
}

使用值運行應用程序後,endPoint 將登錄到控制台。

使用工廠

工廠是另一種類型的提供者,可用於非常特殊的用例。

一般我們提供服務的時候,在模塊加載的時候就解決了,但是也有可能需要動態創建實例的實例,這就是我們需要工廠的地方。

例如,獲取數據庫連接,讓客戶端在​​運行時決定連接哪個數據庫。

運行以下命令來創建兩個服務:

nest generate service dbprovider
nest generate service client

client.service.ts 中添加以下代碼 .

import { Injectable } from '@nestjs/common';

@Injectable()
export class ClientService {

    getClientDetails() {
        return {
            client: 'test',
            db: 'databaseconnection'
        }
    }
}

接下來,打開 dbprovider.service.ts 並添加以下代碼。

import { Injectable } from '@nestjs/common';

@Injectable()
export class DbproviderService {

    constructor(private connection: string) { }

    getProductsForClient() {
        return this.connection;
    }
}

dbprovider.service.ts ,這裡我們使用的是字符串屬性,如果你嘗試運行這個應用程序,你會得到錯誤,因為這是不允許的。

我們要創建 DbproviderService 的實例 在運行時,所以我們需要再做一個改變。打開app.module.ts 並刪除 DbproviderService 來自 providers 屬性。

NestJS 讓我們創建工廠,創建一個新文件 connection.provider.ts ,並添加以下代碼。

import { ClientService } from "./client/client.service";
import { DbproviderService } from "./dbprovider/dbprovider.service";

export const dbConnectionFactory  = {
    provide: 'ClientConnection',
    useFactory : (clientSerice: ClientService) => {
        return new DbproviderService(clientSerice.getClientDetails().db);
    },
    inject: [ClientService]
}

在這裡,我們正在創建一個 DbproviderService 的新實例 通過獲取 dbClientService .您可以在這裡使用多個服務,您只需在 useFactory 中以逗號分隔傳遞它們 並且需要在inject中添加相同的服務 屬性。

現在我們完成了工廠,讓我們註冊並使用它。打開app.module.ts 並添加 dbConnectionFactoryproviders 屬性。

接下來,打開 product.service.ts 並添加以下代碼。

constructor(@Inject(PRODUCT) product: Product,
    @Inject('ClientConnection') dbProviderService: DbproviderService){
    console.log(product.endPoint);
    console.log(dbProviderService.getProductsForClient())
}

結論

我們學習瞭如何在 NestJS 中創建和使用不同類型的提供程序,我們使用依賴注入設計模式來使用服務,這也可以讓您實現單一職責。

服務是單例的,但我們也可以控制Services的範圍,我們會在下一篇文章中看到。


Tutorial JavaScript 教程
  1. 1. ReactJS 簡介以及我們為什麼要使用它

  2. 如何使用 Node.js 開發聊天機器人

  3. Docker 化 Angular 應用程序

  4. 如何通過兩步從 WP API 獲取所有 WordPress 帖子

  5. 如何在 textarea(HTML 標記)中編寫 JavaScript 對像以使用 documentQuerySelector 獲取該對象

  6. 我喜歡建立我的投資組合。

  7. 當必須用撇號包裝時,如何隱藏 API 密鑰?

  1. 最流行的 JS 框架概述

  2. 使用 nodeJS 和 mySQL 進行機器學習的全棧 Webscrapper

  3. 用 JavaScript 編寫 Rock、Paper 和 Scissors 的 3 種方法(初級、中級和高級方法)

  4. 什麼是解析?

  5. 視頻系列:VueJS 和 Supabase.io 入門,“開源 Firebase 替代方案”

  6. 4 種不同的方式來創建 Vue 組件

  7. 使用閉包和工廠函數在 JavaScript 中模擬私有變量

  1. 使用 React Navigation v5 在 React Native 應用程序中進行深度鏈接

  2. 如何將 Facebook Login API 集成到您的 React 應用程序中

  3. ENOENT:在 react-native 項目中安裝 react-navigation 時沒有這樣的文件或目錄

  4. 什麼是 Javascript 中的提升?