HTTP模块 HTTP module

导读

Axios 是一个功能丰富的 HTTP 客户端包,被广泛使用。Nest 包装了 Axios 并通过内置的 HttpModule 将其公开。HttpModule 导出 HttpService 类,该类公开基于 Axios 的方法来执行 HTTP 请求。该库还将生成的 HTTP 响应转换为 Observables

提示

您还可以直接使用任何通用的 Node.js HTTP 客户端库,包括 gotundici

安装

要开始使用它,我们首先安装所需的依赖项。

bash
$ npm i --save @nestjs/axios axios

入门

安装过程完成后,要使用 HttpService,首先导入 HttpModule

ts
@Module({
  imports: [HttpModule],
  providers: [CatsService],
})
export class CatsModule {}

接下来,使用普通的构造函数注入来注入 HttpService

提示

HttpModuleHttpService@nestjs/axios 包导入。

ts
TS
ts
@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  findAll(): Observable<AxiosResponse<Cat[]>> {
    return this.httpService.get('http://localhost:3000/cats')
  }
}
提示

AxiosResponse 是从 axios 包导出的接口($ npm i axios)。

所有 HttpService 方法都返回一个包装在 Observable 对象中的 AxiosResponse

配置

Axios 可以使用各种选项进行配置,以自定义 HttpService 的行为。此处 了解有关它们的更多信息。要配置底层 Axios 实例,请在导入 HttpModule 时将可选选项对象传递给它的 register() 方法。此选项对象将直接传递给底层 Axios 构造函数。

ts
@Module({
  imports: [
    HttpModule.register({
      timeout: 5000,
      maxRedirects: 5,
    }),
  ],
  providers: [CatsService],
})
export class CatsModule {}

异步配置

当您需要异步传递模块选项而不是静态传递时,请使用 registerAsync() 方法。与大多数动态模块一样,Nest 提供了几种处理异步配置的技术。

一种技术是使用工厂函数:

ts
HttpModule.registerAsync({
  useFactory: () => ({
    timeout: 5000,
    maxRedirects: 5,
  }),
})

与其他工厂提供商一样,我们的工厂函数可以是异步的,并且可以通过inject注入依赖项。

ts
HttpModule.registerAsync({
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    timeout: configService.get('HTTP_TIMEOUT'),
    maxRedirects: configService.get('HTTP_MAX_REDIRECTS'),
  }),
  inject: [ConfigService],
})

或者,您可以使用类而不是工厂来配置HttpModule,如下所示。

ts
HttpModule.registerAsync({
  useClass: HttpConfigService,
})

上面的构造在 HttpModule 中实例化了 HttpConfigService,并使用它来创建一个选项对象。请注意,在此示例中,HttpConfigService 必须实现 HttpModuleOptionsFactory 接口,如下所示。HttpModule 将对所提供类的实例化对象调用 createHttpOptions() 方法。

ts
@Injectable()
class HttpConfigService implements HttpModuleOptionsFactory {
  createHttpOptions(): HttpModuleOptions {
    return {
      timeout: 5000,
      maxRedirects: 5,
    }
  }
}

如果您想重用现有的选项提供程序,而不是在HttpModule内创建私有副本,请使用useExisting语法。

ts
HttpModule.registerAsync({
  imports: [ConfigModule],
  useExisting: HttpConfigService,
})

直接使用 Axios

如果你觉得 HttpModule.register 的选项不够用,或者你只想访问 @nestjs/axios 创建的底层 Axios 实例,你可以通过 HttpService#axiosRef 来访问,如下所示:

ts
@Injectable()
export class CatsService {
  constructor(private readonly httpService: HttpService) {}

  findAll(): Promise<AxiosResponse<Cat[]>> {
    return this.httpService.axiosRef.get('http://localhost:3000/cats')
    //                      ^ AxiosInstance interface
  }
}

完整示例

由于 HttpService 方法的返回值是 Observable,我们可以使用 rxjs - firstValueFromlastValueFrom 以承诺的形式检索请求的数据。

ts
import { catchError, firstValueFrom } from 'rxjs'

@Injectable()
export class CatsService {
  private readonly logger = new Logger(CatsService.name)
  constructor(private readonly httpService: HttpService) {}

  async findAll(): Promise<Cat[]> {
    const { data } = await firstValueFrom(
      this.httpService.get<Cat[]>('http://localhost:3000/cats').pipe(
        catchError((error: AxiosError) => {
          this.logger.error(error.response.data)
          throw 'An error happened!'
        }),
      ),
    )
    return data
  }
}
提示

访问 RxJS 关于 firstValueFromlastValueFrom 的文档,了解它们之间的区别。