GraphQL 需要模块外部与内部 GraphQLObjectType

Alw*_*nny 2 javascript node.js graphql graphql-js

可能标题不适合我的问题,但让我解释一下我的情况。我正在使用 Graphql 架构。这是我的初始 schema.js 文件https://github.com/sany2k8/graphql-udemy/blob/master/schema/schema.js

它工作正常然后我决定将它拆分为不同的小文件,例如root_query_type.jsmutation.jsuser_type.jscompany_type.js。所有文件都作为模块导出并循环需要。例如 -

用户类型.js

const graphql = require('graphql');
const axios = require('axios');
const { GraphQLObjectType, GraphQLString, GraphQLInt } = graphql;
//const CompanyType = require('./company_type'); // *this line causing error*


const UserType = new GraphQLObjectType({
    name: "User",
    fields: () => ({
        id:{ type: GraphQLString},
        firstName:{ type: GraphQLString},
        age:{ type: GraphQLInt},
        company :{
            type: require('./company_type'), // *this line fix the error*
            resolve(parentValue, args){
                return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
                    .then(res => res.data)
            }
        }
    })
});

module.exports = UserType;
Run Code Online (Sandbox Code Playgroud)

company_type.js

const graphql = require('graphql');
const axios = require('axios');
const { GraphQLObjectType, GraphQLString, GraphQLList } = graphql;
const UserType = require('./user_type');


const CompanyType = new GraphQLObjectType({
    name: "Company",
    fields: ()=> ({
        id: { type: GraphQLString},
        name: { type: GraphQLString},
        description: { type: GraphQLString},
        users:{
            type: new GraphQLList(UserType),
            resolve(parentValue, args){
                return axios.get(`http://localhost:3000/companies/${parentValue.id}/users`)
                    .then(res => res.data)
            }
        }
    })
});

module.exports = CompanyType;
Run Code Online (Sandbox Code Playgroud)

在我的user_type.js文件中,当我const CompanyType = require('./company_type');像这样在文件顶部使用const UserType 时,它​​向我显示以下错误消息

错误:User.company 字段类型必须是输出类型但得到:[object Object]。

但是如果我注释掉该行并直接放置它,那么它就可以工作。

company :{
                type: require('./company_type'),
                resolve(parentValue, args){
                    return axios.get(`http://localhost:3000/companies/${parentValue.companyId}`)
                        .then(res => res.data)
                }
            }
Run Code Online (Sandbox Code Playgroud)

所以基本上我的问题是为什么它不能const CompanyType = require('./company_type');type: require('./company_type'). 我可能是一个简单的逻辑问题,但它无法找到。请帮助我。

Dan*_*den 5

您看到的行为并非特定于 GraphQL,而是一般的节点。您的模块中存在循环依赖关系,这导致您的require内部语句user_type.js解析为company_type.js.

根据文档,给定两个相互需要的模块(a.jsb.js):

main.js加载时a.js,则a.js依次加载b.js。此时, b.js尝试加载a.js. 为了防止无限循环,将导出对象的 未完成副本a.js返回给b.js 模块。b.js然后完成加载,并将其exports对象提供给a.js模块。

在导出定义中移动 require 语句是一种解决方案。您还可以将您的导出定义移动您的 require 调用之上以获得相同的效果。这个问题更深入地研究了循环依赖,并提供了一些替代解决方案。

作为旁注,这是我建议不要以编程方式声明 GraphQL 模式的原因之一。您可以使用graphql-toolsgenerate- schema 从 GraphQL 语言文档生成模式。这可以防止您处理潜在的循环依赖项,并导致更具可读性的架构。您也可以轻松地模块化您的架构;您的类型定义只是字符串,而您的解析器只是对象——两者都可以轻松组合。