Apollo graphQL Server subscription initial response

544 Views Asked by At

I've successfully got graphQL subscriptions to work with help of the documentation.

The subscription returns a pubsub.asyncIterator("MY_TOPIC"), which I then can send messages trough. Now I would like to send the current value to the new subscriber, and only the new subscriber, on subscription.

As the pubsub.asyncIterator("MY_TOPIC")() is a shared async iterator I guess I need a wrapper, which itsef is an async iterator, which returns the current value and thereafter "becomes" the shared pubsub.asyncIterator("MY_TOPIC")().

Any ideas on how to accomplish that?

const mySubscription = {
  subscribe: async (parent, args, context, info) => {
    return context.pubsub.asyncIterator("MY_TOPIC")
  },
  resolve: payload => {
    return payload
  },
}

EDIT: It seems like sometime a good night of sleep is worth a lot.

const mySubscription = {
  subscribe: async (parent, args, context, info) => {
    return (async function* () {
      yield 123; //let this be my current state
      for await (const val of context.pubsub.asyncIterator("MY_TOPIC")) {
        yield val;
      }
    })()
  },
  resolve: payload => {
    return payload
  },
}

As far as I can see I just create a wrapper generator, which returns my desired value and afterwards iterates over the pubsub async iterator. I tried that before, but forgot about the await in the for await of loop. And obviously the pubsub AsyncIterator is not syncronously iterable. Are there any sideffects I'm missing?

1

There are 1 best solutions below

1
On

It sounds like you need a filter for your subscription, have a look at the example here...

It may look like this:

import { withFilter } from 'graphql-subscriptions';

const currentUsers = [];
const resolvers = {
  Subscription: {
    myTopic: {
      subscribe: withFilter(
        () => pubsub.asyncIterator('MY_TOPIC'),
        (payload, variables) => {
          // Only push an update if it is a new subscriber
          if (!currentUsers.includes(variables.username)) {
            currentUsers.push(variables.username);
            return true;
          }
          return false;
        },
      ),
    }
  }
}