【问题标题】:Apollo - multiple graphql subscriptions from child components in Angular appApollo - Angular 应用程序中子组件的多个 graphql 订阅
【发布时间】: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 缓存。

标签: angular apollo apollo-client


【解决方案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 个实时订阅。

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2017-09-19
    • 2020-10-08
    • 2020-11-08
    • 2022-12-12
    • 2019-01-18
    • 2017-09-01
    • 2020-07-07
    • 2018-12-16
    相关资源
    最近更新 更多