实现GraphQL遇技术问题,求排查MenuItemData类型定义代码
嘿,我看了你贴的GraphQL类型代码片段,先帮你梳理几个容易踩坑的地方,大概率能解决你的问题:
1. resolve函数参数命名别踩坑
你在resolve里把参数命名成了MenuItemData,这和你的类型名完全一样,虽然语法上没毛病,但后续维护的时候很容易搞混。GraphQL社区里一般都用parent或者source来命名这个参数,代表当前父节点传递过来的数据,改完会清晰很多:
resolve(parent) { return PageRepository.getPageById(parent.page).exec(); }
2. 异步查询的错误处理不能少
看你的代码用了.exec(),应该是用Mongoose这类ODM吧?那getPageById().exec()返回的是Promise,虽然直接return没问题,但一旦数据库查询失败,GraphQL只会返回模糊的错误信息,很难定位问题。建议用async/await搭配try/catch来处理,还能顺便校验查询结果是否存在:
async resolve(parent) { try { const page = await PageRepository.getPageById(parent.page).exec(); if (!page) { throw new Error(`找不到ID为${parent.page}的页面`); } return page; } catch (err) { throw new Error(`获取页面失败:${err.message}`); } }
3. 检查代码是否完整闭合
你贴的代码最后是return MenuRepository.getMenuById(MenuItemData.menu).e...,明显是截断了,要确保你完整调用了.exec(),不然会返回Query对象而不是实际的数据库数据,GraphQL根本没法正确解析这个字段。
4. 循环依赖的类型要处理好
你用了fields: () => ({})这种函数式写法来解决循环依赖,这点是对的,但要确认menuItemType和menuType这两个类型在menuItemDataType定义前已经被声明了——哪怕只是用var提前声明一下,不然会出现引用未定义的错误。
5. NonNull约束要匹配实际数据情况
你给page和menu加了GraphQLNonNull,意味着这两个字段必须有值且不能为null。但你得确认你的数据源里,每一条MenuItemData都有有效的page和menuID,而且数据库查询一定能返回对应的结果。如果存在查询不到的情况,GraphQL会直接抛出非空错误,这时候要么去掉NonNull约束,要么在resolve里提前做校验兜底。
最后给你贴个修正后的完整示例片段参考:
export const menuItemDataType = new GraphQL.GraphQLObjectType({ name: 'MenuItemData', fields: () => ({ staticUrl: { type: GraphQL.GraphQLString }, page: { type: new GraphQL.GraphQLNonNull(menuItemType), async resolve(parent) { try { const page = await PageRepository.getPageById(parent.page).exec(); if (!page) { throw new Error(`找不到ID为${parent.page}的页面`); } return page; } catch (err) { throw new Error(`获取页面失败:${err.message}`); } } }, menu: { type: new GraphQL.GraphQLNonNull(menuType), async resolve(parent) { try { const menu = await MenuRepository.getMenuById(parent.menu).exec(); if (!menu) { throw new Error(`找不到ID为${parent.menu}的菜单`); } return menu; } catch (err) { throw new Error(`获取菜单失败:${err.message}`); } } } }) });
如果还有具体的报错信息(比如运行时控制台报错、查询返回null或异常),可以补充细节,这样能更精准定位问题~
内容的提问来源于stack exchange,提问作者Tomáš Kacálek

