Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

apollo "Subscription field must return Async Iterable. Received: undefined"

I have a mutation that fires the channel event 'countIncr', but I don't see the active corresponding subscription fire with the event payload.

UPDATE: I've made several updates to this posting and now I'm changing the title to be more representative of where I am.

I'm getting a graphqlPlayground error

"Subscription field must return Async Iterable. Received: undefined"

TGRstack reproduction i'm having trouble with: https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/

Working Reproduction without TGRstack: https://github.com/Falieson/fullstack-apollo-subscription-example

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here Frontend: https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/blob/master/counter-ui/src/app/routes/Home/HomePage.tsx

const COUNTER_SUBSCRIPTION = gql`
subscription onCountIncr {
  count
}
`

const Counter = () => (
  <Subscription
    subscription={COUNTER_SUBSCRIPTION}
  >
    {({ data, loading }) => {
      console.log({loading, data})
      return loading
        ? <h1>Loading ...</h1>
        : data.count
          ? <h2>Counter: {data.count}</h2>
          : <h1>Counter Subscription Not Available</h1>
    }}
  </Subscription>
)

BE Resolvers: https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/blob/master/counter-service/src/gql/Resolvers.ts

BE Schema: https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/blob/master/counter-service/src/gql/Schema.ts

BE Controller: https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/blob/master/counter-service/src/gql/Counter.ts

const count = {
  resolve: data => {
    console.log('CounterSub>', {data})
    return data
  },
  subscribe: () => pubsub.asyncIterator(['countIncr'])
}

const CounterSubscriptions = {
  count
}
async function countIncr(root: any, args: any, context: any) {
  const count = Counter.increment()
  await pubsub.publish('countIncr', count )
  console.log('countIncr', '>>>', { count })
  return count
}

Here is the service log after you've run through the #getting started instructions in the Readme.md

[FE] GET /favicon.ico 200 2.465 ms - 1551                   # WEBCLIENT LOADED
[BE] CounterSub> { data: undefined }                        # SUBSCRIPTION REQUEST
[BE] { data: [Object: null prototype] { count: null } }     # SUBSCRIPTION RESULT
[BE] POST / 200 21.254 ms - 24
[BE] 2019-05-10 11:37:20 [info]:     HELLO                  # APOLLO CLIENT CONNECTED AGAIN (why always 2?)
[BE] countIncr >>> { count: 1 }                             # MUTATION REQUEST
[BE] { data: [Object: null prototype] { countIncr: 1 } }    # MUTATION RESPONSE
[BE] POST / 200 13.159 ms - 25
[BE] countIncr >>> { count: 2 }                             # MUTATION REQUEST
[BE] { data: [Object: null prototype] { countIncr: 2 } }    # MUTATION RESPONSE
[BE] POST / 200 4.380 ms - 25

UPDATE

Incase you've tried to clone the repo and after running nps it didn't work its because there was a step missing in nps setup. I've pushed an update to the stack with the nps setup improved.

UPDATE 2

updated code and links in question per latest commit

UPDATE 3

Some people have suggested that pubsub should be a single import. I've updated the code but this creates a new error:

Error: Apollo Server requires either an existing schema, modules or typeDefs

UPDATE 4

numerous minor changes trying to hunt down import/export bugs(?) now getting the error. I fixed this error by hardening imports (there was some issue w/ the index file not properly exporting).

"message": "Subscription field must return Async Iterable. Received: undefined"

Working Reproduction without TGRstack: https://github.com/Falieson/fullstack-apollo-subscription-example

Update 5

I demodularized/decomposed a bunch of things to make it easier to trace whats going on but still getting the same error

like image 916
Falieson Avatar asked May 10 '19 18:05

Falieson


People also ask

Does the resolver for a subscription work in Apollo server?

We are trying to get the resolver for a subscription working in Apollo Server. The subscription works when it is a top-level field (i.e. directly under Subscription at the schema root).

How do I use usesubscription in Apollo client?

Like useQuery, useSubscription returns an object from Apollo Client that contains loading, error, and data properties you can use to render your UI. The following example component uses the subscription we defined earlier to render the most recent comment that's been added to a specified blog post.

What is the subscribetomore function in Apollo client?

Whenever a query returns a result in Apollo Client, that result includes a subscribeToMore function. You can use this function to execute a followup subscription that pushes updates to the query's original result. The subscribeToMore function is similar in structure to the fetchMore function that's commonly used for handling pagination.

What is the error in Apollo-Server- Express?

Error in apollo-server-express: Subscription field must return Async Iterable. Received: undefined #2653 Error in apollo-server-express: Subscription field must return Async Iterable. Received: undefined #2653


1 Answers

I solved this issue in 2 places

  1. ApolloServer.installSubscriptionHandler() TEMPORARILY replacing middleware.apolloSubscriptions() . I configure the subscriptions middleware following this guide: https://www.apollographql.com/docs/graphql-subscriptions/express so I'm going to guess there's something messed up w/ the version of one of those packages or the guide itself.

    ApolloServer.installSubscriptionHandlers(ws)

    const listener = ws.listen({port: config.PORT}, () => {
      middleware.apolloSubscriptions(ws)
      // middleware.apolloSubscriptions(ws)
  1. terminatingLink and getMainDefinition are necessary for the client https://github.com/TGRstack/tgr-apollo-subscription-example-microservice/commit/75b6165f2dc1d035a41f1129f7386a1e18c7ba53#diff-2c47ef33b8ed0e4c893cbc161bcf7814R37
  private _terminatingLink = split(
    ({ query }) => {
      const { kind, operation } = getMainDefinition(query)
      return (
        kind === 'OperationDefinition' && operation === 'subscription'
      )
    },
    this._wsLink,
    this._httpLink,
  )
like image 172
Falieson Avatar answered Sep 22 '22 08:09

Falieson