【问题标题】: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”新手。我被困在双向模式映射中。帖子 作者。使用graphqlgraphql-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 功能有关吗?

【问题讨论】:

    标签: node.js graphql graphql-relay


    【解决方案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中会出现的循环问题。

    谢谢。

    【讨论】:

      猜你喜欢
      • 2021-08-24
      • 2020-06-28
      • 2019-04-19
      • 2023-01-01
      • 2022-12-22
      • 2021-05-08
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      相关资源
      最近更新 更多