基于graphql-js合并多GraphQL对象解析器的最优方案问询
当然有可行的方法!在graphql-js中合并多个GraphQL对象的解析器是日常开发里很实用的技巧,尤其是当你把Schema和解析器按模块拆分维护的时候。结合你提到的Store、Employee这些实体,我给你分享几种优先基于graphql-js原生实现的方案:
方法1:手动合并解析器对象
这是最直接的方式,利用JavaScript的对象展开运算符(...)或者Object.assign来合并多个解析器对象。比如你可能把Store的解析器和Employee的解析器分开写,最后合并成一个完整的解析器集合。
举个例子:
// 单独定义Store的解析器 const storeResolvers = { Store: { region: (parent) => parent.region, // 枚举类型的解析通常直接返回值即可 employees: async (parent, args, context) => { // 从SQL数据库查询该门店的所有员工 return context.db.query('SELECT * FROM employees WHERE store_id = $1', [parent.id]); } } }; // 单独定义Employee的解析器 const employeeResolvers = { Employee: { id: (parent) => parent.id, name: (parent) => parent.name // 其他Employee字段的解析逻辑 } }; // 合并解析器 const resolvers = { ...storeResolvers, ...employeeResolvers }; // 之后创建Schema时传入这个合并后的resolvers const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', fields: { store: { type: StoreType, args: { id: { type: GraphQLID } }, resolve: async (parent, args, context) => { return context.db.query('SELECT * FROM stores WHERE id = $1', [args.id]); } } } }), types: [StoreType, EmployeeType] });
这种方式适合小型项目或者解析器拆分不多的场景,简单易懂,不需要额外依赖。
方法2:封装递归合并工具函数
如果你的解析器嵌套层级比较深(比如某个类型的字段还有自己的子解析器),手动展开可能会遗漏嵌套的字段。这时候可以写一个简单的工具函数来递归合并解析器:
function mergeResolvers(...resolversArray) { return resolversArray.reduce((merged, resolvers) => { for (const typeName in resolvers) { if (!merged[typeName]) { merged[typeName] = {}; } // 合并当前类型下的所有字段解析器 merged[typeName] = { ...merged[typeName], ...resolvers[typeName] }; } return merged; }, {}); } // 使用方式 const resolvers = mergeResolvers(storeResolvers, employeeResolvers, /* 其他解析器 */);
这个函数会遍历每个解析器对象,把相同类型下的字段解析器合并在一起,避免手动处理嵌套的麻烦。我在中大型项目里经常用这种方式,能节省不少重复代码。
方法3:结合Schema拼接(进阶)
如果你是把Schema按模块拆分定义的(比如每个实体对应一个Schema片段),可以先拼接Schema类型,再合并对应的解析器。比如:
// 定义Store模块的Schema和解析器 const storeSchema = new GraphQLObjectType({ /* ... */ }); const storeResolvers = { /* ... */ }; // 定义Employee模块的Schema和解析器 const employeeSchema = new GraphQLObjectType({ /* ... */ }); const employeeResolvers = { /* ... */ }; // 拼接根Query类型 const rootQuery = new GraphQLObjectType({ name: 'Query', fields: { store: storeSchema.getFields().store, // 其他查询字段 } }); // 合并解析器 const resolvers = mergeResolvers(storeResolvers, employeeResolvers); // 创建最终Schema const schema = new GraphQLSchema({ query: rootQuery, types: [storeSchema, employeeSchema] });
这种方式适合模块划分非常清晰的大型项目,每个模块独立维护自己的Schema和解析器,最后统一拼接合并。
需要注意的是,如果多个解析器里有相同类型的相同字段,后面的解析器会覆盖前面的,所以要确保字段解析器的优先级符合你的预期。
内容的提问来源于stack exchange,提问作者Ken Bellows
相关产品推荐
相关产品推荐

