节点 - GraphQL - Ad.user字段类型必须是输出类型但得到:未定义

时间:2018-01-16 17:22:41

标签: node.js output undefined graphql circular-dependency

在AdType中使用UserType似乎存在循环依赖性问题。

这是我的UserType文件:UserType

这是我的AdType文件:AdType

如果我尝试使用下面的代码,我会收到错误“Ad.user字段类型必须是输出类型,但得到:未定义”,即使我正确导入了UserType。

import { UserType } from '../User/user.graphql.model'
import { UserSchema } from '../User/user.mongoose.model'

const user =  {
  type: UserType,
  resolve(parentValue, args) {
    return UserSchema.findById(parentValue.user);
  }
};

//------------------------------
// Ad Type
//------------------------------
export const AdType = new GraphQLObjectType({
  name: 'Ad',
  fields: () => ({
    id,
    user,
    title,
    views,
    availability,
... more code

如果我在导入后尝试在AdType中控制日志UserType,则表示未定义,但当我将其用作:

//------------------------------
// Ad Type
//------------------------------
export const AdType = new GraphQLObjectType({
  name: 'Ad',
  fields: () => ({
    id,
    user: {
      type: UserType,
      resolve(parentValue, args) {
        return UserSchema.findById(parentValue.user);
      }
    },
    title,
... more code

它按预期工作,它只是不允许我拉出代码来分隔常量。 我以相同方式导入和使用的所有其他类型按预期工作,将广告导入用户也可以,但将用户导入广告似乎已中断。两者中的代码基本相同,只是不同的信息。

1 个答案:

答案 0 :(得分:0)

  

我已经在使用字段:()=> ({})懒惰加载字段以避免循环依赖的问题,所以这个问题实际上是在敲打我的脑袋。

但你没有正确地做到这一点。 Javascript没有懒惰的评价。这意味着在调用函数时,但在评估user变量定义的时间点,不确定const的值。此时,变量UserType不保留任何值,因此未定义。调用函数时需要进行对象定义。如果仍然不清楚,我可以提供详细的解决方法。

尝试内联定义用户类型或使其成为函数:

const user = () => ({ type: UserType, /* ... */ })

export const AdType = new GraphQLObjectType({
  name: 'Ad',
  fields: () => ({
    id,
    user: user(),
    title,
    views,
    availability,

我不确定为什么你把你的字段拉成单独的常量,你的代码看起来不那么大,它提高了可读性,但当然我可能是错的。

好的,让我们看看模块是如何解决的。为了使这更容易,我使用CJS,因为你很可能无论如何都要将代码转换下来,ES模块只是慢慢地进入节点。

// user.graphql.model.js
const adModule = require('ad.graphql.model.js');

// Node tries to resolve ad.graphql.model.js
const userModule = require('user.graphql.model.js');
// Ups, this one has been resolved already and required this as dependency.
// We have no other choice than to assign an empty object here
// userModule is {}
const user =  {
  type: userModule.UserType, // undefined
  resolve(parentValue, args) {
    return UserSchema.findById(parentValue.user);
  }
};
// finish this module and return to user.graphql.model.js
// adModule now contains the resolved module
const adModule = require('ad.graphql.model.js');
// finish module and replace {} with actual module content in ad.graphql.model.js
// userModule contains UserType
const userModule = require('user.graphql.model.js');

const ads = {
  type: new GraphQLList(asModule.AdType), // GraphQLObjectType
}

// Now your Schema does build/inits itself after the config has been specified
// (and all modules have been resolved)
// imagine user being a function now taht is called on Schema init
const user = () => ({
  type: userModule.UserType, // GraphQLObjectType
  /* ... */
})