Javascript 如何使用GraphQL中继连接修复循环依赖关系

Javascript 如何使用GraphQL中继连接修复循环依赖关系,javascript,graphql,relayjs,relay,graphql-js,Javascript,Graphql,Relayjs,Relay,Graphql Js,我已将我与它自己的文件的连接分离出来,并可以在我的根查询中使用它(在类型中定义连接时,它工作得很好),但当尝试通过将其导入到该类型来使用它时,我只是返回连接: 错误:PageEdge.node字段类型必须是输出类型,但Get:未定义 我可以让连接在我的QueryType中工作,但不能在PageType中工作。我的模式大致如下 QueryType { pages: [PageType] } PageType { _id: string pages: [PageType] } 这里有

我已将我与它自己的文件的连接分离出来,并可以在我的根查询中使用它(在类型中定义连接时,它工作得很好),但当尝试通过将其导入到该类型来使用它时,我只是返回连接:

错误:PageEdge.node字段类型必须是输出类型,但Get:未定义

我可以让连接在我的QueryType中工作,但不能在PageType中工作。我的模式大致如下

QueryType {
  pages: [PageType]
}

PageType {
  _id: string
  pages: [PageType]
}
这里有一个指向项目repo的链接,其中包含graphql内容(我刚刚用it erroring推送了一个commit以查看所有代码):

我制作了QueryType和PageType字段thunks(似乎可以解决大多数人的问题的解决方案),并尝试使用接口制作thunk:

interfaces: () => [nodeInterface]
我认为这对于任何与用户和朋友一起构建应用程序的人来说都是一个非常常见的问题

UserType: {
  friends: [UserType]
}
我的页面类型:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;
import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;
import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);
import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};
我的页面连接:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;
import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;
import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);
import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};
我的节点界面:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;
import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;
import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);
import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};
我的类型注册表:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;
import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;
import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);
import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};
导入连接工作的我的查询类型

import {
  GraphQLObjectType as ObjectType,
  GraphQLList as List,
  GraphQLString as StringType,
} from 'graphql';
import { connectionArgs, connectionFromArray, connectionDefinitions } from 'graphql-relay';
import { nodeField } from '../nodeInterface';
import PageType from './PageType';
import { getPageList } from '../queries/googleDatastore/pageQueries';
import PageConnection from './connections/PageConnection';

const QueryType = new ObjectType({
  name: 'QueryType',
  fields: () => ({
    pages: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (obj, args) => {
        const response = [];
        try {
          const pageEdge = await getPageList();
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        } catch (err) {
          console.log('pages err', err);
        }
        return response;
      },
    },
    node: nodeField,
  }),
});

export default QueryType;
这个问题的资源我一直在努力解决:

import { nodeInterface } from '../nodeInterface';
import PageConnection from './connections/PageConnection';

const PageType = new ObjectType({
  name: 'Page',
  description: 'Everything you see can be placed inside a page.',
  fields: () => ({
    id: globalIdField('Page', page => page._id),
    _id: {
      type: new NonNull(ID),
      description: 'A unique id used to instantly locate this page inside the database',
    },
    pageEdge: {
      type: PageConnection,
      args: connectionArgs,
      resolve: async (page, { args }, { loaders }) => {
        if (page.pageEdge) {
          const pageEdge = await loaders.pageLoader.loadMany(page.pageEdge);
          const connection = connectionFromArray(pageEdge, args);
          return connection;
        }
      },
    },
  }),
  interfaces: () => [nodeInterface],
});

export default PageType;
import { connectionDefinitions } from 'graphql-relay';

import PageType from '../PageType';

const { connectionType: PageConnection } = connectionDefinitions({
  name: 'Page',
  nodeType: PageType,
});

export default PageConnection;
import { nodeDefinitions } from 'graphql-relay';
import { getNode, getNodeType } from './type-registry';

export const { nodeInterface, nodeField } = nodeDefinitions(getNode, getNodeType);
import { fromGlobalId } from 'graphql-relay';
require('babel-polyfill');

const types = {};

export const registerType = (model, type, lookupFn) => {
  types[type.name] = { model, type, lookupFn };
};

export const getNode = async (globalId) => {
  const { type: typeName, id } = fromGlobalId(globalId);
  console.log('getNode', globalId, typeName, id);

  if (types[typeName]) {
    const object1 = await types[typeName].lookupFn(id);
    const Class = types[typeName].model;
    // let result  = Object.create(types[typeName].model, object1);
    const result = new Class(object1);
    console.log('getNode result', result);
    return result;
  }
  return null;
};

export const getNodeType = (obj) => {
  const keys = Object.keys(types);
  let ret = null;
  keys.map((typeName) => {
    if (obj instanceof types[typeName].model) {
      ret = types[typeName].type;
    }
    return true;
  });
  return ret;
};
这个回购协议的一部分是我实施的,目的是让连接首先发挥作用


只需删除
PageType.js顶部的
import PageConnection
,并使用运行时要求:

...
pageEdge: {
  type: require('./connections/PageConnection'),
  args: connectionArgs,
...

此返回的错误:Page.pageEdge字段类型必须是输出类型,但得到了:[object object]。还尝试将require放入函数中,并调用类型:pages()和pages()[0/1],但仍然为nothingTry
require('./connections/PageConnection')。默认值
OMG非常感谢!!!!花了超过3天的时间来处理这个问题,并准备将连接恢复到该类型。我还必须补充一点,因为它给了我“无法读取未定义的”之后的属性”。在resolve方法中,我用{…args}替换了{args},它修复了itI,在我看到这个解决方案之前,它快要发疯了。救了我一天,谢谢你。