NestJS 与 Apollo 数据源

Posted

技术标签:

【中文标题】NestJS 与 Apollo 数据源【英文标题】:NestJS with Apollo DataSource 【发布时间】:2020-11-04 12:48:42 【问题描述】:

我一直在尝试使用 NestJS 重新创建 Apollo tutorial。但是当我尝试将apollo-datasource-rest 与 NestJS 一起使用时,从外部数据源获取数据时失败,并出现以下错误:

[Nest] 29974   - 07/14/2020, 9:33:20 PM   [ExceptionsHandler] Cannot read property 'fetch' of undefined +125971ms
TypeError: Cannot read property 'fetch' of undefined

似乎数据源类没有被正确注入到解析器中,但我不知道为什么?

// The data source class
@Injectable()
class LaunchAPI extends RESTDataSource 
  constructor() 
    super();
    this.baseURL = 'https://api.spacexdata.com/v2/';
  
  async getLaunchById( launchId ) 
    return await this.get('launches',  flight_number: launchId );
  


// The Nest resolver
@Resolver('launch')
@Injectable()
export class LaunchResolver 
  constructor(private readonly  launchAPI: LaunchAPI) 

  @Query('getLaunch')
  async getLaunch(
    @Args('id') id: string
  ) 
    return await this.launchAPI.getLaunchById( launchId: id )
  


// The app module
@Module(
  imports: [
    GraphQLModule.forRoot(
      dataSources,
      context: ( req ) => 
        if (req) 
          return  headers: req.headers ;
        
      ,
      typePaths: ['./**/*.graphql'],
      definitions: 
        path: join(process.cwd(), 'src/graphql.schema.ts'),
        outputAs: 'class',
      ,
      debug: true,
    )
  ],
  controllers: [AppController],
  providers: [AppService, LaunchAPI, LaunchResolver],
)
export class AppModule 

将 Apollo 的数据源与 Nest 解析器结合使用的最佳方式是什么?

【问题讨论】:

【参考方案1】:

我能够通过在我的每个解析器方法上使用 @Context 装饰器来解决问题,以便获取 apollo 数据源服务(例如 dataSources),而不是在解析器类中注入数据源。所以更新后的样子如下:

// The Nest resolver
@Resolver('launch')
@Injectable()
export class LaunchResolver 
  @Query('getLaunch')
  async getLaunch(
    @Context('dataSources')  launchAPI : DataSources,
    @Args('id') id: string
  ) 
    return await launchAPI.getLaunchById( launchId: id )
  


// app.module.ts

// set up any dataSources our resolvers need
const dataSources = () => (
  launchAPI: new LaunchAPI(),
);

@Module(
  imports: [
    GraphQLModule.forRoot(
      dataSources,
      context: ( req ) => 
        if (req) 
          return  headers: req.headers ;
        
      ,
      typePaths: ['./**/*.graphql'],
      definitions: 
        path: join(process.cwd(), 'src/graphql.schema.ts'),
        outputAs: 'class',
      ,
      debug: true,
    )
  ],
  controllers: [AppController],
  providers: [AppService, LaunchAPI, LaunchResolver],
)
export class AppModule 

【讨论】:

如果您的 Resolver 和 RestDataSource IE 之间有一个服务层,您将如何解决此问题:Resolver --> BL Service --> RestDataSource? 这种方法存在一些问题。照原样,1. 您无法在 LaunchAPI 中正确利用 DI,因为它手动添加为数据源并在 DI 上下文之外。 2. LaunchAPI 设置为单例范围。它应该是请求范围,但最终它是无关紧要的,因为在这种方法中完全绕过了 DI。

以上是关于NestJS 与 Apollo 数据源的主要内容,如果未能解决你的问题,请参考以下文章

通过 Apollo Server (NestJS) 处理异常

如何使用 NestJS GraphQL 实现 NuxtJS Apollo

Nestjs 中的 Graphql Apollo 上传返回无效值

nodejs升级后运行apollo服务器的问题(使用nestjs和fastify)

NestJS + TypeORM:使用两个或更多数据库?

基于typescript 强大的 nestjs 框架试用