如何使用 GraphQL Relay 连接修复循环依赖
Posted
技术标签:
【中文标题】如何使用 GraphQL Relay 连接修复循环依赖【英文标题】:How to fix circular dependency with GraphQL Relay connections 【发布时间】:2017-11-15 13:37:21 【问题描述】:我已经将我的连接与它自己的文件分开,并且可以在我的根查询中使用它(当连接在类型中定义时它工作正常),但是当尝试通过将它导入到类型来使用它时,连接是因为我刚回来:
错误:PageEdge.node 字段类型必须是输出类型但得到:未定义
我可以让连接在我的 QueryType 中工作,但不是 PageType。我的架构大致是这样的。
QueryType
pages: [PageType]
PageType
_id: string
pages: [PageType]
这是一个指向graphql东西所在的项目repo的链接(我刚刚推送了一个提交,它出错以查看所有代码): https://github.com/DaveyEdwards/myiworlds/tree/master/src/data
我已经制作了 QueryType 和 PageType 字段 thunk(似乎可以解决大多数人的问题的解决方案)并且还尝试从接口中制作一个 thunk:
interfaces: () => [nodeInterface]
我认为对于任何与用户和朋友一起构建应用程序的人来说,这是一个非常常见的问题。
UserType:
friends: [UserType]
我的页面类型:
import nodeInterface from '../nodeInterface';
import PageConnection from './connections/PageConnection';
const PageType = new ObjectType(
name: 'Page',
description: 'Everything you see can be placed inside a page.',
fields: () => (
id: globalIdField('Page', page => page._id),
_id:
type: new NonNull(ID),
description: 'A unique id used to instantly locate this page inside the database',
,
pageEdge:
type: PageConnection,
args: connectionArgs,
resolve: async (page, args , loaders ) =>
if (page.pageEdge)
const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
const connection = connectionFromArray(pageEdge, args);
return connection;
,
,
),
interfaces: () => [nodeInterface],
);
export default PageType;
我的页面连接:
import connectionDefinitions from 'graphql-relay';
import PageType from '../PageType';
const connectionType: PageConnection = connectionDefinitions(
name: 'Page',
nodeType: PageType,
);
export default PageConnection;
我的节点界面:
import nodeDefinitions from 'graphql-relay';
import getNode, getNodeType from './type-registry';
export const nodeInterface, nodeField = nodeDefinitions(getNode, getNodeType);
我的类型注册表:
import fromGlobalId from 'graphql-relay';
require('babel-polyfill');
const types = ;
export const registerType = (model, type, lookupFn) =>
types[type.name] = model, type, lookupFn ;
;
export const getNode = async (globalId) =>
const type: typeName, id = fromGlobalId(globalId);
console.log('getNode', globalId, typeName, id);
if (types[typeName])
const object1 = await types[typeName].lookupFn(id);
const Class = types[typeName].model;
// let result = Object.create(types[typeName].model, object1);
const result = new Class(object1);
console.log('getNode result', result);
return result;
return null;
;
export const getNodeType = (obj) =>
const keys = Object.keys(types);
let ret = null;
keys.map((typeName) =>
if (obj instanceof types[typeName].model)
ret = types[typeName].type;
return true;
);
return ret;
;
导入的连接工作的我的 QueryType
import
GraphQLObjectType as ObjectType,
GraphQLList as List,
GraphQLString as StringType,
from 'graphql';
import connectionArgs, connectionFromArray, connectionDefinitions from 'graphql-relay';
import nodeField from '../nodeInterface';
import PageType from './PageType';
import getPageList from '../queries/googleDatastore/pageQueries';
import PageConnection from './connections/PageConnection';
const QueryType = new ObjectType(
name: 'QueryType',
fields: () => (
pages:
type: PageConnection,
args: connectionArgs,
resolve: async (obj, args) =>
const response = [];
try
const pageEdge = await getPageList();
const connection = connectionFromArray(pageEdge, args);
return connection;
catch (err)
console.log('pages err', err);
return response;
,
,
node: nodeField,
),
);
export default QueryType;
我一直在努力解决这个问题的资源:
这个 repo 的一部分是我为了让连接首先工作而实现的 https://github.com/bondz/learn-graphql-relay/blob/47211fdec44ce4bb10f487bddfc7411e5690b894/src/types/projectConnection.js
Edge.node field type must be Output Type but got: undefined
https://github.com/graphql/graphql-js/issues/612
https://github.com/graphql/graphql-js/issues/373
https://gist.github.com/fbaiodias/77406c29ddf37fe46c3c
【问题讨论】:
【参考方案1】:只需删除 PageType.js
顶部的 import PageConnection
并使用运行时要求:
...
pageEdge:
type: require('./connections/PageConnection'),
args: connectionArgs,
...
【讨论】:
返回错误:Page.pageEdge 字段类型必须为输出类型,但得到:[object Object]。 还尝试将 require 放入函数并调用类型: pages() 和 pages()[0/1] 仍然没有 试试require('./connections/PageConnection').default
天啊,非常感谢你们!!!!花了超过 3 天的时间来解决这个问题,并且正准备将连接放回类型中。我还必须再添加一件事,因为它给了我“无法在未定义之后读取属性”。我在 resolve 方法中用 ...args 替换了 args 并修复了它
在看到这个解决方案之前,我快要发疯了。拯救了我的一天,谢谢。以上是关于如何使用 GraphQL Relay 连接修复循环依赖的主要内容,如果未能解决你的问题,请参考以下文章
GraphQL、Relay 和 Mongodb (mongoose) 如何获取数组