如何在没有循环依赖的情况下在 GraphQL 中拆分模式?
Posted
技术标签:
【中文标题】如何在没有循环依赖的情况下在 GraphQL 中拆分模式?【英文标题】:How to split schema in GraphQL without having circular dependencies? 【发布时间】:2016-12-24 19:48:20 【问题描述】:我的问题类似于javascript circular dependency in GraphQL code,但我的问题不在结构和数据库级别,而是在 javascript (ES6) 中。
我的架构定义变得太大,但我看不到在哪里可以将文件分割成碎片。根据不同的对象类型进行切割似乎是合乎逻辑的,但这会带来循环依赖,类似于这个非常简化的非工作示例:
// -- file A.js
import bConnection, getBs from 'B';
export class A /*...*/ ;
export var getA = (a) => /*...*/ ;
export var getAs = (array_of_as) => /*...*/ ;
export var aType = new GraphQLObjectType (
name: 'A',
fields: () => (
bs:
type: bConnection,
/*...*/
,
resolve: (a, args) => connectionFromPromisedArray (
getBs (a.bs)
),
/*...*/
),
interfaces: () => [ require ('./nodeDefs').nodeInterface ],
/*...*/
)
export var
connectionType: aConnection,
edgeType: aEdge
= connectionDefinitions (
name: 'A',
nodeType: aType
);
// -- file B.js
import aConnection, getAs from 'A';
export class B /*...*/ ;
export var getB = (b) => /*...*/ ;
export var getBs = (array_of_bs) => /*...*/ ;
export var bType = new GraphQLObjectType (
name: 'B',
fields: () => (
as:
type: aConnection,
/*...*/
,
resolve: (b, args) => connectionFromPromisedArray (
getAs (b.bs)
),
/*...*/
),
interfaces: () => [ require ('./nodeDefs').nodeInterface ],
/*...*/
)
export var
connectionType: bConnection,
edgeType: bEdge
= connectionDefinitions (
name: 'B',
nodeType: bType
);
// -- file nodeDefs.js
import
fromGlobalId,
nodeDefinitions,
from 'graphql-relay';
import A, getA, aType from 'A'
import B, getB, bType from 'B'
export var nodeInterface, nodeField = nodeDefinitions (
(globalId) =>
var type, id = fromGlobalId (globalId);
if (type === 'A')
return getA (id);
else if (type === 'B')
return getB (id);
,
(obj) =>
if (obj instanceof A)
return aType;
else if (obj instanceof B)
return bType;
)
// -- file schema.js
import
GraphQLObjectType,
GraphQLSchema,
from 'graphql';
import nodeField from './nodeDefs';
var queryType = new GraphQLObjectType (
name: 'Query',
fields: () => (
node: nodeField,
/*...*/
),
);
对此有通用方法或最佳实践吗?
【问题讨论】:
您找到其他解决方案了吗? 【参考方案1】:我也有同样的问题。我认为更简洁的解决方案是使用 gruntjs concat。
grunt.initConfig(
concat:
js:
src: ['lib/before.js', 'lib/*', 'lib/after.js'],
dest: 'schema.js',
);
使用此配置,您可以将架构拆分为多个文件,创建最终的 schema.js。
before.js 可能是这样的:
import
GraphQLObjectType,
GraphQLInt,
GraphQLString,
GraphQLSchema,
GraphQLList,
GraphQLNonNull
from 'graphql';
import db from '../models/index.js';
import Auth from '../classes/auth';
after.js 可能是这样的:
const Schema = new GraphQLSchema(
query: Query,
mutation: Mutation
)
export default Schema;
其他文件将包含以下对象:
const Funcionario = new GraphQLObjectType(
name: 'Funcionario',
description: 'This represent a Funcionario',
fields: () =>
return
id:
type: GraphQLInt,
resolve(funcionario, args)
return funcionario.id;
,
CPF:
type: GraphQLString,
resolve(funcionario, args)
return funcionario.CPF;
,
nome:
type: GraphQLString,
resolve(funcionario, args)
return funcionario.nome;
,
sobrenome:
type: GraphQLString,
resolve(funcionario, args)
return funcionario.sobrenome;
,
sessions:
type: new GraphQLList(Session),
resolve(funcionario, args)
return funcionario.getSessions();
)
【讨论】:
谢谢您,我接受您的解决方案,因为它确实解决了我的问题。我仍在试图找到一种不使用 grunt 的方法,因为仅仅因为这个问题而使用它似乎有点矫枉过正。但是如果没有别的办法,我就实现这个。 如果你想试一试 Apollo 的 graphql-tools,它会真正简化你的代码并使其更具可读性。如果您使用它,我已经编写了一个名为 schemaglue.js 的工具来解决您的确切问题。我在这里写过关于缩放和组织你的 GraphQL 代码的文章:hackernoon.com/…希望这会有所帮助。【参考方案2】:见https://github.com/francoisa/todo/tree/master/server/graphql/types
todoType.js 引用了 viewerType.js 中定义的 viewerType
viewerType.js 从 todoType 导入
【讨论】:
以上是关于如何在没有循环依赖的情况下在 GraphQL 中拆分模式?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用公用文件夹和 php artisan 的情况下在 laravel graphql-playground 中加载 schema.graphql
如何在没有任何延迟的情况下在android中循环播放音频文件?
如何在没有要映射的对象数组的情况下在 React.js 中循环和渲染元素?
Gatsby + Contentful - 如何在不重新启动服务器的情况下在本地重做 GraphQL 查询(npm run dev)?