简体   繁体   中英

Apollo - multiple graphql subscriptions from child components in Angular app

The general advice (in Apollo documentation) is to create small, focused queries inside child components.

So we have several such queries and they are all "live" queries where we listen for value changes.

We also have a graphql subscription that updates a part of the cache that is read by these queries.

So every time the subscription sends an update, the queries automatically update.

This works great but I'm not sure where should I subscribe to the subscription.

This is what we're doing now:

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();
  }
}

Since there are multiple instances of AComponent , is it ok that all of them subscribe to the subscription?

Since you didn't provide any code I'm just guessing but I would ' activate ' the subscription in a standalone service which can be initialized in some top level component. If you then want to access it in components, inject it as standard service.

// 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
  }

  //...
}

Judging by your another question about observable splitting, this service can be then used to expose partial queries.

After testing my solution I found out that you get an event for each time you subscribe to a subscription.

In our case, we subscribed multiple times to the same subscription and received multiple identical websocket messages.

In order to fix that we now wrap our subscriptions in a service that makes sure we only subscribe once:

class PostsUpdateService {
  private subscribed: boolean;

  constructor(private postsSubscription: Subscription<Post>) {}

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

In our case, we are ok with never unsubscribing since we always have at least 1 live subscription.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM