Apollo - Angular 应用程序中子组件的多个 graphql 订阅

Posted

技术标签:

【中文标题】Apollo - Angular 应用程序中子组件的多个 graphql 订阅【英文标题】:Apollo - multiple graphql subscriptions from child components in Angular app 【发布时间】:2021-10-13 18:01:17 【问题描述】:

一般建议(在 Apollo 文档中)是在子组件中创建小的、集中的查询。

所以我们有几个这样的查询,它们都是我们监听值变化的“实时”查询。

我们还有一个 graphql 订阅,用于更新这些查询读取的部分缓存。

所以每次订阅发送更新时,查询都会自动更新。

这很好用,但我不确定我应该在哪里订阅。

这就是我们现在正在做的事情:

class AComponent 
  ngOnInit() 
    // Multiple instances of AComponent watch the same query.
    // Works great - one request is sent to the server and
    // all the others use the cache
    this.queryService1.watch()...
    // And we subscribe to a subscription that might update the cache
    // and cause the query to update
    this.subscription.subscribe();
  


既然AComponent有多个实例,可以全部订阅订阅吗?

【问题讨论】:

这看起来像是一些商店管理的用例,例如 NgRx。但这需要一些剧烈的重构。也许可以使用一些与 NgRx 具有相似和简化逻辑的服务。如果需要,您可以注入服务,并且您不会像那样使用它来耦合子组件和父组件。 @dallows 看不出它是如何解决问题的。问题仍然存在,在哪里订阅订阅。在一个地方或可以在多个地方完成而无需开销 这基本上是 NgRx 所做的。你有一个单一的事实来源,你在每个需要状态切片的组件中订阅它。所以组件中的多个订阅是没有问题的。只是代替父/***组件使用服务。 但我问的是订阅 graphql 订阅。换句话说,“激活”订阅(要求服务器向我们发送更新)。我不需要 NgRX 作为单一的事实来源,因为我已经有了 Apollo 缓存。 【参考方案1】:

由于您没有提供任何代码,我只是在猜测,但我会在独立服务中“激活”订阅,该服务可以在某些***组件中初始化。如果您想在组件中访问它,请将其作为标准服务注入。

// app.component
export class AppComponent implements OnInit 

  constructor(private apolloQueryService: ApolloQueryService)  

  ngOnInit() 
    this.apolloQueryService.initialize();
  
  //...


// ApolloQueryService
// I have no experience with Apollo, this is just to illustrate
@Injectable(
  providedIn: 'root',
)
export class ApolloQueryService 
  apolloSub$;

  constructor(private apollo: Apollo) 

  initialize(): void 
    this.apolloSub$ = this.appolo.someQuery.subscribe();
    // add others if necessary
  

  //...

根据您关于可观察拆分的另一个问题判断,此服务可用于公开部分查询。

【讨论】:

感谢您在我的问题上投入时间:-)。你的回答从几个方面来说是错误的。首先,如果您想要的只是执行查询的服务,那么您将扩展 Apollo 的 Query 类。其次,我问的是 graphql 订阅,而不是查询。第三,我希望你不会觉得它冒犯,但如果你没有 Apollo 的经验,那么你可能无法回答这个问题。我非常熟悉 Angular、NgRX 等。这个问题是关于与 Apollo 合作的正确方式。 未采纳,但正如我所说,由于您一开始没有提供任何代码,因此很难弄清楚您要实现什么【参考方案2】:

在测试了我的解决方案后,我发现每次订阅订阅都会收到一个事件。

在我们的例子中,我们多次订阅同一个订阅并收到多个相同的 websocket 消息。

为了解决这个问题,我们现在将订阅包装在一项服务中,以确保我们只订阅一次:

class PostsUpdateService 
  private subscribed: boolean;

  constructor(private postsSubscription: Subscription<Post>) 

  subscribe() 
    if (!this.subscribed) 
      this.subscribed = true;
      this.postsSubscription.subscribe().subscribe();
    
  

在我们的例子中,我们可以从不退订,因为我们总是至少有 1 个实时订阅。

【讨论】:

以上是关于Apollo - Angular 应用程序中子组件的多个 graphql 订阅的主要内容,如果未能解决你的问题,请参考以下文章

Apollo Angular 无法从 GraphQL/MongoDB 获取数据

apollo.watchQuery 堆栈/重复 = 性能问题?

Angular Apollo GraphQL watchQuery 与订阅

Angular2:父子组件通信

订阅 Angular Apollo 查询 observable 会带来旧值、缓存问题

网络错误:req.headers.forEach Apollo Client Angular4