Jeff Lowery
Jeff Lowery

Reputation: 2597

graphql-tools: lazy fetching?

I'm trying to simplify a graphql server using Apollo's graphql-tools. I want to do lazy-fetching, but not able to return a promise the way I could when using javascript classes as the resolvers.

Here's what I got:

Schema

type Customer {
    details: Contact!
    addresses: [Address]!
}
    extend type Query {
        customers(first: Int = 0, next: Int = 50): [Customer]
        customer(id: Int!): Customer
    }

Resolver

const domain1Resolvers = {
    Query: {
        customers: (_, {
            first,
            next
        }) => customers(first, next)
    }
};

resolving method:

const customers = (first, next) => {
    return new Promise(resolve => {
        var q =
            `
                SELECT *, company as organization FROM customer
                ORDER BY id DESC
                LIMIT ?, ?`;
        sql.query(q, [first, next], function(err, rows) {
            if (err) {
                throw Error(err);
            }
            resolve(rows.map(r => {
                return {
                    details: r,
                    addresses: () => getAddresses(r.id),
                }
            }));
        });
    })
};

The method getAddresses is invoked only if addresses is requested. In the class-based approach, I am able to have getAddresses return a Promise, but it will complain about not returning an Iterable if I try that using this mechanism. There must be some way of fetching addresses only when requested, but drawing a blank and so far not found an example.

Upvotes: 1

Views: 743

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84657

To resolve a field on Customer only when it is requested, you would want to utilize the resolver for that particular field rather than the resolver for the customers query. Your resolvers would look something like this:

const domain1Resolvers = {
  Query: {
    customers: (_, {
      first,
      next
    }) => customers(first, next)
  },
  Customer: {
    addresses: ({ details: { id } }) => getAddresses(id)
  },
};

Upvotes: 2

Related Questions