Nestjs - 使用可用的第 3 方库自定义 类 的正确方法是什么

Nestjs - What is the right approach to have custom classes using 3rd party libraries available

我是 NestJS 的新手,我没有找到任何明确的说明来做我需要做的事情。

我想使用 NestJS 构建我的后端,我以前从未使用过它,但只听说过它的好消息。所以我要构建的后端服务器将使用来自 npmjs 的名为 ccxt 的第 3 方模块。在一个普通的节点应用程序中,我会创建一个随机的 class 例如 CryptoManager,导入 ccxt 模块并编写一些 运行 在设定的时间间隔或其他什么的函数。然后我将创建一个控制器 class 来实例化 CryptoManager class 的对象,然后我可以 return 它的响应。

但是我应该如何使用 NestJS 来做到这一点?我需要做什么才能让自定义 class 即 运行 后台任务在其他嵌套控制器/服务等中可用?

这个 class 只是应该执行第 3 方 (ccxt) 模块函数并将结果存储在 database.But 我希望能够从所有执行这个 classes 方法nestjs 应用程序中的点(来自所有模块)。

我希望我的问题很清楚,如果不清楚请告诉我。

您需要 Modules and Providers 的组合才能以“嵌套方式”执行此操作,然后您可以在整个应用程序中使用依赖项注入。

一般来说,添加第三方库的方法如下:

  1. 创建一个模块来包装您的库,例如“CryptoManagerModule”。
  2. 创建一个提供 CCXT 库的自定义提供程序,并将其添加到您的 providers 数组。
  3. 创建服务“CryptoManagerService”,并将 CCXT 注入构造函数。
  4. 从您的模块中导出“CryptoManagerService”,以便您可以将其注入到应用的其余部分。
  5. (可选)将您的模块标记为“全局”,这样您只需在 AppModule 中配置该模块一次即可使其对所有其他模块可用。

里面crypto-manager.module.ts

import { DynamicModule, Module, Provider } from '@nestjs/common';
import { CryptoManagerService } from './crypto-manager.service';
import * as ccxt from 'ccxt';

// Add any config options you need, like API keys, etc
export interface CryptoManagerModuleOptions {
  global?: boolean;
}

export const KRAKEN_CLIENT_TOKEN = 'KRAKEN_CLIENT_TOKEN';

export class CryptoManagerModule {
  static forRoot(options: CryptoManagerModuleOptions): DynamicModule {
    // An example of injecting a single class of ccxt.  Note this is only available
    // within this module.
    const krakenProvider: Provider = {
      provide: KRAKEN_CLIENT_TOKEN,
      useValue: new ccxt.kraken(),
    };

    return {
      module: CryptoManagerModule,
      providers: [krakenProvider, CryptoManagerService],
      // Exports can be @Inject()'ed to other files, and if global
      // is set, then forRoot only needs to be called in the AppModule
      exports: [CryptoManagerService],
      global: options.global,
    };
  }
}

里面crypto-manager.service.ts

import { Inject, Injectable } from '@nestjs/common';
import { KRAKEN_CLIENT_TOKEN } from './crypto-manager.module';
import { kraken } from 'ccxt';

@Injectable()
export class CryptoManagerService {
  constructor(@Inject(KRAKEN_CLIENT_TOKEN) private kraken: kraken) {}

  loadKrakenMarkets() {
    return this.kraken.loadMarkets();
  }
}

里面app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CryptoManagerModule } from './crypto-manager/crypto-manager.module';

@Module({
  controllers: [AppController],
  providers: [AppService],
  // Make sure to call forRoot
  imports: [CryptoManagerModule.forRoot({ global: true })],
})
export class AppModule {}

最后,在 app.service.ts 中使用它的示例。我没有对这个文件做任何特别的事情,你只会看到记录到控制台的结果。

import { Inject, Injectable } from '@nestjs/common';
import { CryptoManagerService } from './crypto-manager/crypto-manager.service';

@Injectable()
export class AppService {
  constructor(private cryptoManagerService: CryptoManagerService) {}

  getHello(): string {
    this.cryptoManagerService.loadKrakenMarkets().then(console.log);
    return 'Hello World!';
  }
}

这样做可以让你在测试时轻松模拟 kraken,允许你在 forRoot 中传递配置变量,以防你想跨项目重用它,并且是一种模式这在 Nest 社区中已经很普遍了。

我为此创建了 nestjs-ccxt NestJS CCXT 模块包装器 https://www.npmjs.com/package/nestjs-ccxt

首先像导入任何其他模块一样导入 CcxtModule

import { CcxtModule } from 'nestjs-ccxt';

@Module({
  imports: [CcxtModule.forRoot({ ... })],
})
export class AppModule {}

接下来在您的服务中使用普通构造函数注入注入 CcxtService

@Injectable()
export class ExchangeService {
  constructor(private ccxtService: CcxtService) {}

  async getBtcUsdtTicker() {
    const client = await this.ccxtService.getClient('binance');
    const ticker = await client.fetchTicker('BTC/USDT');
    return ticker;
  }
}