javascript - GraphQL.js - 使用接口(interface)作为 resolveType 函数中的默认(回退)类型

标签 javascript node.js interface graphql graphql-js

如果提供的类型均不匹配,我将尝试在 resolveType 函数中返回泛型类型。下面的示例显示了这个问题:API 工作得很好,支持 UserTypeMovieType,直到在数据库中添加了 BookType(GraphQL 模式不支持) .

const {
  graphql,
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLInterfaceType
} = require("graphql");

const DATA = [
  {
    // UserType
    name: "catherine woolf",
    nick: "catherine"
  },
  {
    // MovieType
    name: "cat woman",
    director: "Jack Wolfgang"
  },
  {
    // --- missing type --- (BookType)
    name: "cats secrets",
    author: "Nicky Glace"
  }
];

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
};

const SearchableType = new GraphQLInterfaceType({
  name: "Searchable",
  fields: {
    name: { type: GraphQLString }
  },
  resolveType: resolveType
});

const UserType = new GraphQLObjectType({
  name: "User",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    nick: { type: GraphQLString }
  }
});

const MovieType = new GraphQLObjectType({
  name: "Movie",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    director: { type: GraphQLString }
  }
});

const schema = new GraphQLSchema({
  types: [MovieType, UserType, SearchableType],
  query: new GraphQLObjectType({
    name: "RootQueryType",
    fields: {
      search: {
        type: new GraphQLList(SearchableType),
        args: {
          text: { type: new GraphQLNonNull(GraphQLString) }
        },
        resolve(_, { text }) {
          return DATA.filter(d => d.name.indexOf(text) !== -1);
        }
      }
    }
  })
});

const query = `
  {
    search(text: "cat") {
      name
      ... on User {
        nick
      }
      ... on Movie {
        director
      }
    }
  }
`;

graphql(schema, query).then(result => {
  console.log(JSON.stringify(result, null, 2));
});

所以现在这段代码以错误结束:

"Abstract type Searchable must resolve to an Object type at runtime for field RootQueryType.search with value \"[object Object]\", received \"undefined\". Either the Searchable type should provide a \"resolveType\" function or each possible types should provide an \"isTypeOf\" function."

这并不奇怪,因为目前 resolveType 可能不会返回任何类型。

解决方法

Crate 类型包含与接口(interface) SearchableType 相同的字段(1 对 1 实现):

const _SearchableType = new GraphQLObjectType({
  name: '_Searchable',
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
  }
});

将其用作后备类型:

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
  return _SearchableType;
};

并将其添加到 schema 定义中的 types 中:

types: [MovieType, UserType, SearchableType, _SearchableType],

但是这个解决方案的问题是在这样的文档中存在这个虚拟 _SearchableType:

problematic _SearchableType in docs

问题

有什么方法可以在 resolveType 中返回接口(interface) SearchableType 或等效接口(interface)?对我来说,关键点是在文档中隐藏这种“后备类型”。

最佳答案

GraphQL 是强类型的,在解析联合和接口(interface)时不支持泛型或某种“回退”机制。归根结底,如果您的底层数据层正在返回您尚未在模式中实现的某种类型,最简单的解决方案就是将该类型简单地添加到您的模式中。迁移到数据库和更改架构应该齐头并进。

如果您想从存储层派生架构,我建议您查看类似 PostGraphile 的内容(以前称为 PostGraphQL)。

也就是说,如果您一心想使用变通方法,则可以回退到现有类型之一:

const resolveType = data => {
  if (data.nick) {
    return UserType
  }
  return MovieType
}

现在一本书的名字仍然可以访问,只要你在界面上查询它而不是其中一种类型。这种方法的唯一缺点是将为一本书返回特定于电影的字段并将解析为 null,但这不会导致任何问题,除非它们在您的架构中明确定义为非 null。

关于javascript - GraphQL.js - 使用接口(interface)作为 resolveType 函数中的默认(回退)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49806296/

相关文章:

iPhone UITableView 在使用自定义单元格时出现卡顿现象。如何让它平滑滚动?

javascript - 加载 Highcharts 文档时 DOM 节点计数增加 (Chrome)

javascript - native JavaScript 中的动画输入

javascript - 如何在 vscode 中查看全 Angular 代码

node.js - 在 try/catch block 中等待两个 promise 导致 "Unhandled promise rejection"

javascript - Node.js:WAITING异步调用的响应

go - 在 Go 中,如何检查接口(interface)是否实现了结构的所有导出方法?

interface - F# 和接口(interface)实现的成员

javascript - 使用 JavaScript 和 Jade 添加到 localStorage

javascript - 如何禁用 jQuery UI Datepicker 上日期选择器的关闭