NestJS GraphQL 数据源
Posted
技术标签:
【中文标题】NestJS GraphQL 数据源【英文标题】:NestJS GraphQL DataSources 【发布时间】:2019-06-28 07:05:55 【问题描述】:警告以下代码不正确,需要根据请求创建数据源。
请勿使用以下代码
我正在尝试将 apollo-rest-datasource
与 NestJS 一起使用。我看到的缺点是数据源不参与 NestJS 的 DI 系统。
我可以通过让 NestJS 实例化单例数据源,然后使用 GraphQLModule.forRootAsync
将这些实例注入 Apollo 服务器的 dataSources
属性来解决此问题。
GraphQLModule.forRootAsync(
imports: [
DataSourcesModule
],
useFactory: (...args: DataSource[]) =>
return
typePaths: ['./**/*.graphql'],
context: (req: req: Request) => ( token: req.headers.authorization ),
playground: true,
dataSources: () =>
let dataInstances = as any;
args.forEach(arg =>
const dataSource = arg as any;
dataInstances[dataSource.constructor.name] = arg;
);
return dataInstances;
,
;
,
inject: [...dataSources]
我现在让 DI 在我的 DataSource 中工作,并且可以在解析器中使用 DI 来包含我的 DataSource 实例(而不是从 GraphQL 上下文访问)。虽然这有效,但感觉不对。
对于 NestJS 的 DI 和 Apollo GraphQL 上下文是否有更好的方法?
【问题讨论】:
您好,我目前正在研究将 Nest 与 GraphQL 结合使用,请问您为什么决定使用 apollo rest 数据源而不是常规的 nest http 客户端?感谢您的帮助! Apollo 数据源提供了一种缓存机制来防止重复的 http 响应。 【参考方案1】:我能够通过在我的每个解析器方法上使用 @Context
装饰器来解决这个问题,以便获取数据源。以here 为例的完整答案。
【讨论】:
【参考方案2】:RESTDataSource 看起来只是一个普通的类。您应该能够简单地应用 @Injectable()
装饰器并将它们视为常规的 Nest 服务。这将允许您将依赖项注入到它们中,并将数据源注入到您的解析器中,而无需像您展示的那样在 GraphQLModule 中引导事物。
const RESTDataSource = require('apollo-datasource-rest');
import Injectable from '@nestjs/common';
@Injectable()
class MoviesAPI extends RESTDataSource
// Inject whatever Nest dependencies you want
constructor(private readonly someDependency: SomeDependency)
super();
this.baseURL = 'https://movies-api.example.com/';
async getMovie(id)
return this.get(`movies/$id`);
async getMostViewedMovies(limit = 10)
const data = await this.get('movies',
per_page: limit,
order_by: 'most_viewed',
);
return data.results;
@Injectable()
class ResolverClass
// Inject your datasources
constructor(private readonly moviesApi: MoviesAPI)
您只需确保将您的 DataSource 类放入适当的 Nest 模块的提供者中,如果还需要从其他模块中使用它们,则可以选择导出它们。
更新:
由于数据源也需要传递给 ApolloServer,因此您可以通过引入自己的装饰器来应用到每个数据源,然后使用反射来“发现”应用程序中存在的所有源,从而可能以更嵌套的方式执行此操作。这不是目前记录良好的内容,但您可以查看一些 Nest 源代码中的示例,了解如何完成此操作。 For reference here's the code that discovers all of the @Resolver
decorated classes for the GraphQL module.
它基本上归结为使用ModulesContainer
和MetadataScanner
来查找应用程序中存在的所有提供程序,然后过滤以查找哪些提供程序应用了您的自定义装饰器。 (例如@DataSource()
)。
我认为你现在拥有的不一定是一个大问题,但如果你以这种方式实现它,你就不必担心每次都要记住添加新的数据源。
【讨论】:
是的,这就是我正在做的事情,但是 Apollo Server 需要将 DataSources 定义为datasources
的属性,以便使用其他 Apollo Server 功能对其进行属性实例化。
我想我得到的是你上面的作品。这就是我目前正在做的事情。把这两个概念混在一起感觉很奇怪。我想没关系?!
@cgatian 我已经更新了答案,为您提供一些提示,告诉您如何以更类似于 NestJS 的方式实现此功能,从而自动发现您的数据源
好建议,我不知道存在。
如果您不使用 DataSource 类中的方法 willSendRequest
(例如,将令牌添加到请求标头中),它将起作用。我可以实现的唯一方法是将数据源字典传递到GraphQLModule
。以上是关于NestJS GraphQL 数据源的主要内容,如果未能解决你的问题,请参考以下文章
GraphQL介绍&使用nestjs构建GraphQL查询服务
nestjs graphql - 保留数据并将其用于其他请求
使用 NestJS、TypeORM、GraphQL 更新具有实体之间关系的 PSQL 表