Axios 是一个功能强大且被广泛使用的 HTTP 客户端库。Nest 对其进行了封装,并通过内置的 HttpModule 提供统一的接口支持。该模块会导出 HttpService,它基于 Axios 提供多种便捷方法用于发起 HTTP 请求,并默认将响应结果封装为 Observable 流,便于与响应式编程模式集成。
开始使用前,请先安装相关依赖包:
npm install @nestjs/axios axios依赖安装完成后,首先需要在目标模块中导入 HttpModule,以便在服务中使用 HttpService:
import { HttpModule } from '@nestjs/axios'
@Module({
imports: [HttpModule],
providers: [CatsService],
})
export class CatsModule {}接着,即可通过依赖注入的方式在服务中获取 HttpService 实例:
import type { HttpService } from '@nestjs/axios'
import type { AxiosResponse } from 'axios'
@Injectable()
export class CatsService {
constructor(private readonly httpService: HttpService) {}
findAll(): Observable<AxiosResponse<Cat[]>> {
return this.httpService.get('http://localhost:3000/cats')
}
}AxiosResponse 是由 axios 包导出的类型定义,用于描述响应结果的结构(可通过
npm install axios 安装)。
通过 HttpService 发起的所有请求都会返回一个 Observable<AxiosResponse<T>> 对象,其中 T 表示响应数据的泛型类型。这种响应式结构非常适合与 Nest 的响应流控制、拦截器等机制配合使用。
Axios 提供了丰富的配置选项,允许你灵活定制 HttpService 的行为。你可以在 Axios 官方文档中查看更多配置项的详细说明。
在 HttpModule 中配置底层的 Axios 实例非常简单,只需在通过 register() 方法导入模块时,传入一个可选的配置对象,该对象会原样传递给 Axios 的构造函数:
@Module({
imports: [
HttpModule.register({
timeout: 5000,
maxRedirects: 5,
}),
],
providers: [CatsService],
})
export class CatsModule {}当你需要以异步方式(而非静态对象)提供模块配置时,可以使用 registerAsync() 方法。和多数动态模块一样,Nest 提供了多种灵活的异步配置策略。
最常见的一种方式是通过工厂函数返回配置对象:
HttpModule.registerAsync({
useFactory: () => ({
timeout: 5000,
maxRedirects: 5,
}),
})工厂函数可以是同步的,也可以是异步函数,并支持通过 inject 注入其他依赖项:
HttpModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
timeout: configService.get('HTTP_TIMEOUT'),
maxRedirects: configService.get('HTTP_MAX_REDIRECTS'),
}),
inject: [ConfigService],
})除了工厂函数外,你也可以使用配置类来实现异步配置:
HttpModule.registerAsync({
useClass: HttpConfigService,
})在上述方式中,Nest 会自动实例化 HttpConfigService 并调用其 createHttpOptions() 方法,用于生成配置对象。为了实现这一点,该类需要实现 HttpModuleOptionsFactory 接口:
@Injectable()
class HttpConfigService implements HttpModuleOptionsFactory {
createHttpOptions(): HttpModuleOptions {
return {
timeout: 5000,
maxRedirects: 5,
}
}
}如果你已经在其他地方定义好了配置提供者,并希望直接复用(而不是让 HttpModule 再创建一个新的实例),可以使用 useExisting 语法:
HttpModule.registerAsync({
imports: [ConfigModule],
useExisting: HttpConfigService,
})registerAsync() 还支持传入 extraProviders,用于添加额外的依赖项。这些额外提供者会与模块中的默认提供者合并:
HttpModule.registerAsync({
imports: [ConfigModule],
useClass: HttpConfigService,
extraProviders: [MyAdditionalProvider],
})当你需要为工厂函数或类的构造函数注入更多依赖时,这种方式非常有用。
如果 HttpModule.register 提供的配置项无法满足你的需求,或者你希望直接调用底层由 @nestjs/axios 创建的 Axios 实例,可以通过 HttpService 的 axiosRef 属性访问该实例。例如:
@Injectable()
export class CatsService {
constructor(private readonly httpService: HttpService) {}
findAll(): Promise<AxiosResponse<Cat[]>> {
return this.httpService.axiosRef.get('http://localhost:3000/cats')
// ^ 这里返回的是 AxiosInstance 接口
}
}由于 HttpService 的方法默认返回的是 Observable,我们可以结合 RxJS 提供的 firstValueFrom 或 lastValueFrom 操作符,将其转换为 Promise,以简化异步处理逻辑。示例代码如下:
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 new Error('请求失败')
})
)
)
return data
}
}如需了解
firstValueFrom 和
lastValueFrom
的差异,请参考 RxJS 官方文档。