Vue.js Apollo set up with batch query processing

Setting up Vue-Apollo is straight forward with many excellent tutorials on line. In my current project I used the Vue CLI to install + set up. A little bit of tweaking for ensuring Auth token was always valid and it was good to go.

No drama

So everything it ticking along nicely when there was a requirement to iterate through an array of ID’s and fire off a graphQL query. Now there could be hundreds of ID’s to process.

Requirements

To run a graphQL query for each ID in an array and aggregate the results into a single collection.

Two possible ways of doing this. The first is to send one query at a time and manage its response – this proved slow and tricky keeping track of potential errors. The second is to let Apollo client handle the logistics using “BatchHttpLink” – it did require a bunch of reading and re-working the Apollo client. In the end batch processing has been working perfectly.

There was a 3rd option, change the Apollo server itself but that want an option.

Solution

My Vue-Apollo config is ./src/vue-apollo.ts

import VueApollo from 'vue-apollo'
import Vue from 'vue';
import { ApolloClient } from 'apollo-client'
import { ApolloLink, split } from 'apollo-link'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { BatchHttpLink } from 'apollo-link-batch-http';
import { getMainDefinition } from 'apollo-utilities'
import { setContext } from 'apollo-link-context';

const AUTH_TOKEN = 'apollo-token'
const HTTP_END_POINT = process.env.VUE_APP_APOLLO_GRAPHQL_CLIENT_URI || "";

const authLink = setContext(async (_, { headers }) => {
  return {
    headers: {
      ...headers,
// This is calls a function to return a valid auth token
      authorization: `Bearer ${ await     Vue.prototype.$auth.getTokenSilently() }`
      }
    }
})

// Set up two different methods the Apollo client can use to handle queries
const httpLink = new HttpLink({ uri: HTTP_END_POINT });
// Add the auth header token
const httpLinkAuth = authLink.concat(httpLink);

// This is the magic batch processing set up
// Other options can be passed. E.g. batch size (default value is 10)
const batchLink = new BatchHttpLink({ uri: HTTP_END_POINT });
const batchLinkAuth = authLink.concat(batchLink);

const link = split(
// split based on operation type
    ({ query }) => {
      const { kind, operation } = getMainDefinition(query)
      return kind === 'OperationDefinition' && operation === 'subscription'
      },
      httpLinkAuth,
      batchLinkAuth,
)

const client = new ApolloClient({
  link: ApolloLink.from([link]),
  cache: new InMemoryCache(),
  connectToDevTools: true
})

// This is the bit you import into main.ts
export const apolloProvider = new VueApollo({
  defaultClient: client
}); 

So far so good. Next how to call and respond to batched queries.

methods: {
    fetchUsers() {
      [
        '6a1603c9-a613-4be5-ae92-123456789',
        ...
        ...
        ....
        'ee55f518-3e65-4118-a0e8-987654321'

      ].forEach(id => {
        this.$apollo.query({
          query: USER_QUERY,
          variables: { id },
        })
          .then(d => {
            this.users.push(d.data.User)
          })
          .catch(e => console.log(e));
      });
    }
  }