Resolver

Root fields (rootValue) declare all the possible entries for our GraphQL API. These Entries are called Resolver.

The syntax of a resolver is as following:

resolverFn(obj, args, context, info) {
	return context.db.loadHumanByID(args.id).then(
	  userData => new Human(userData)
	)
}
  • obj: the rootValue object
  • args: the arguments passed in this function from query
  • context: the current context, used to connect to database or define logged in user, ...
  • info: the meta data for the current query and schema details

Note: by default, if you put this resolverFn in the rootValue, the obj field will be ommited and populated by default and the resolverFn will be called as (args, context, info).

If you want to use the obj field, you can always refer by this. For example:

var rootValue = {
	findAllUserByUsername: (args, context, info) => {
	    console.log("find filter username", obj, args, context, info);
	    return database.filter((user) => user.username == username);
	},
}

var resolverFn = (obj, args, context, info) => {  
	console.log("resolve fn", obj, args, context, info)  
}

if you see in here, the reoslveFn will take 4 parameters including the obj whereas the findAllUserByUsername only takes 3 parameter without the obj

For this fieldResolver function to be effective, we can use within our main entry point graphql() function as following:

graphql({ schema, source, rootValue, fieldResolver: resolverFn }).then((response) => {  
	console.log(JSON.stringify(response, null, 2));  
});

if the resolver name is not in rootValue, GraphQL will fall back to fieldResolver function

Same thing with TypeResolver. However by providing this resolver, we lost the magic behind GraphQL.

GraphQL default resolver

By default we can just query graphql by simply putting in the field type.

For example, if we have:

var database = [
	{ 
		username: "Test1",
		password: "test"
	},
	{ 
		username: "Test2",
		password: "test"
	},
	{ 
		username: "Test3",
		password: "test"
	}
]

With resolvers:

var rootValue = {
	users: () => {  
		return database;  
	},
}

And we query graphql as

{
	users: {
		username
	}
}

as the users return the database, the username is automatically resolved by GraphQL and returns

{
    "data": {
        "users": [
            {
                "username": "Test"
            },
            {
                "username": "Test2"
            }
        ]
    }
}

This is because of GraphQL default resolvers, it assumes that if the resolver for a field isn't provided, the property of the same name should be read and returned

However, if we overwrite with our resolverFn in fieldResolver, this does not work anymore:

graphql({ schema, source, rootValue, fieldResolver: resolverFn }).then((response) => {  
	console.log(JSON.stringify(response, null, 2));  
});

which will returns

{
    "data": {
        "users": null
    }
}