循环模式给出错误为“错误:模式必须包含唯一的命名类型,但包含多个名为“节点”的类型。”

Posted

技术标签:

【中文标题】循环模式给出错误为“错误:模式必须包含唯一的命名类型,但包含多个名为“节点”的类型。”【英文标题】:Cyclic schema giving error as "Error: Schema must contain unique named types but contains multiple types named "Node"." 【发布时间】:2019-03-26 15:29:20 【问题描述】:

我是使用 nodejs 的“GraphQL”新手。我被困在双向模式映射中。帖子 作者。使用graphql 和graphql-relay 模块。

以下是我们使用的两个架构。

--posts.js // here we are requiring authors.js 
const 
    AuthorType,
    schema: AuthorSchema,
    AuthorsConnection
 = require('./authors');

class Post 

const 
    nodeInterface,
    nodeField
 = nodeDefinitions(
    globalId => 
        const 
            type,
            id
         = fromGlobalId(globalId);
        // return based on the id
        return DataSource['posts'][0];
    ,
    obj => 
        console.log(" : PostType : ", PostType);
        // type to be return 
        return Post;
    
);

const PostType = new GraphQLObjectType(
    "name": "PostType",
    "description": "Posts type and it's relevant fields",
    "fields": () => (
        "id": globalIdField('Post'),
        "title": 
            "type": GraphQLString
        ,
        "body": 
            "type": GraphQLString
        ,
        "author": 
            "type": AuthorsConnection,
            "resolve": (parent, argument, root, currentSdl) => 
                console.log("v1, v2, v3, v4  :", parent);
                if (parent.author)
                    return connectionFromArray(DataSource['authors'], )
                return [];
            
        
    ),
    isTypeOf: Post,
    interfaces: [nodeInterface]
);

const 
    connectionType: PostsConnection,
    edgeType: GQLPostEdge
 = connectionDefinitions(
    name: "Post",
    nodeType: PostType
);
module.exports = exports = 
    PostType,
    PostsConnection,
    schema: 
        post: nodeField,
        posts: 
            type: PostsConnection,
            resolve: (root, v2, v3) => 
                return connectionFromArray(DataSource['posts'], );
            
        
    
;

--authors.js // here we have required posts.js

const 
    PostType,
    PostsConnection
 = require('./posts');

class Author 

const 
    nodeInterface,
    nodeField
 = nodeDefinitions(
    globalId => 
        const 
            type,
            id
         = fromGlobalId(globalId);
        // return based on the id
        return DataSource['authors'][0];
    ,
    obj => 
        console.log(" : Authorype : ", Authorype);
        // type to be return 
        return Author;
    
);

const AuthorType = new GraphQLObjectType(
    "name": "AuthorType",
    "description": "Author type and it's relevant fields",
    "fields": () => (
        "id": globalIdField('Author'),
        "firstName": 
            "type": GraphQLString
        ,
        "lastName": 
            "type": GraphQLString
        ,
        authorPosts: 
            type: PostsConnection,
            resolve: (parent, args, root, context) => 
                return connectionFromArray(DataSource['posts'], );
            
        
    ),
    isTypeOf: null,
    interfaces: [nodeInterface]
);

const 
    connectionType: AuthorsConnection,
    edgeType: GQLAuthorEdge
 = connectionDefinitions(
    name: "Author",
    nodeType: AuthorType
);

module.exports = exports = 
    AuthorType,
    AuthorsConnection,
    schema: 
        author: nodeField,
        authors: 
            type: AuthorsConnection,
            resolve: (root, v2, v3) => 
                return connectionFromArray(DataSource['authors'], );
            
        
    
;

一旦我为 GraphQL 合并上述架构,我就会收到以下错误。

Error: Schema must contain unique named types but contains multiple types named "Node".

我试图调试这个问题,以下是我观察到的。

一旦我将“作者”字段从帖子架构更改为 “AuthorsConnection”它开始工作。 或者如果删除“作者”字段 从帖子架构开始工作。

请告诉我这里有什么问题,它与nodeDefinitions 功能有关吗?

【问题讨论】:

【参考方案1】:

确实和nodeDefinitions函数有关。来自graphql-relay 文档:

nodeDefinitions 返回对象可以实现的Node 接口,并返回node 根字段以包含在查询类型中。为了实现这一点,它需要一个函数来将 ID 解析为对象,并确定给定对象的类型。

您调用了两次,这导致 Node 类型被定义了两次,并且您引用了每个:

schema: 
    post: nodeField,

// ...

schema: 
    author: nodeField,

这是导致错误的原因 - 现在有两个无效的 Node 独立实例。

解决方法是只调用一次nodeDefinitions,然后将生成的nodeFieldnodeInterface的引用传递给相关的地方。然后您的globalId => ... 函数将需要查看type 以了解如何获取相关记录,无论是作者还是帖子。

【讨论】:

您好本杰,感谢您的快速回复。只调用一次“nodeDefinitions”就可以了。但是对于大号来说是否可行。要从单个位置获取的类型(如帖子、作者等)。还有其他模块化的方法吗? fetcher 只是一个函数;并从 fromGlobalId 你得到一个类型;那么您可以使用它来查看任意地图并调用相关的提取器(如果存在);所以每种类型都可以在 fetcher map 上注册一个 fetcher 函数。这只是一种方法。【参考方案2】:

连同@Benjie 给出的上述答案。我找到了克服导致Error: Schema must contain unique named types but contains multiple types named "Node". 错误的问题的方法。

以下是我们以模块化方式制作graphql时需要检查的关键点。

不要创建类型的新实例,例如:const PostType = new GraphQLObjectType() 它应该始终发送单个对象而不是每次都发送新对象。 只使用一次nodeDefinations。 检查常见的javascript issue中会出现的循环问题。

谢谢。

【讨论】:

以上是关于循环模式给出错误为“错误:模式必须包含唯一的命名类型,但包含多个名为“节点”的类型。”的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 在 spatie-permission 的 foreach 循环中给出错误

ses.sendmail() 给出 CORS 错误。响应中的“Access-Control-Allow-Origin”标头不得为通配符“*”。凭证模式为“包含”

反应中的简单for循环此代码在for循环中给出错误

vue for循环中的saldo计数器给出无限循环错误

dbus-daemon --session 给出循环包含错误

React Axios API 调用与数组循环给出错误的顺序?