Reputation: 50016
I am trying to get the list of models.
First I have created a model query API. And now I want to get a list by providing ids
.
I know I can use Promise.all
on getModelById
and do some processing to each result I get again.
But is there a way to reuse the individual model query API? Thanks
const ModelType = new GraphQLObjectType({
name: 'Model',
fields: {
id: { type: GraphQLString },
// ...
}
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
model: {
type: ModelType,
args: {
id: { type: GraphQLString }
},
resolve(parentValue, args) {
const { id } = args;
return getModelById(id).then(model => doSomeProcessing(model));
}
},
models: {
type: new GraphQLList(ModelType),
args: {
ids: { type: new GraphQLList(GraphQLString) }
},
resolve(parentValue, args) {
const { ids } = args;
// here I know I can use Promise.all on getModelById and do my doSomeProcessing again for each result I got,
// but is there a way to reuse the model query above? Thanks
}
}
})
});
Upvotes: 0
Views: 359
Reputation: 84897
You cannot reference an existing resolver inside another resolver. The only way you can reuse the logic is by abstracting it out into a separate function that gets called by both resolvers. For example:
const getProcessedModelById = (id) => {
return getModelById(id).then(model => doSomeProcessing(model))
}
// model
resolve(parentValue, args) {
return getProcessedModelById(args.id)
}
// models
resolve(parentValue, args) {
return Promise.all(args.ids.map(id => getProcessedModelById(args.id)))
}
Depending on the kind of processing you're doing on the model, it may be possible to do it through field resolvers on the Model
type. Let's say your Model
type has two fields -- firstName
and lastName
but your model returns a single field called name
. Your doSomeProcessing
is just taking that name and breaking it apart into firstName
and lastName
:
function doSomeProcessing (model) {
const names = model.name.split(' ')
return { firstName: names[0], lastName: names[1] }
}
Instead of doing that, your resolvers could just return whatever getModelById
returns. Then you can encapsulate the "processing" logic inside each field's resolver:
// firstName field
resolve (parentValue) {
return parentValue.name.split(' ')[0]
}
// lastName field
resolve (parentValue) {
return parentValue.name.split(' ')[1]
}
The advantage of this approach is that the "processing" won't actually happen unless that field is requested by the client. In this very simple example, resolving the lastName
field is not expensive, but that may not always be the case. It also very neatly encapsulates logic for fields that are derived from the underlying data layer. However, it can also end up being more expensive (imagine, for example, if the split
call was itself expensive... now we're calling that method twice instead of once).
Upvotes: 1