Javascript 在GraphQL中解析根目录下的自定义类型

Javascript 在GraphQL中解析根目录下的自定义类型,javascript,node.js,graphql,Javascript,Node.js,Graphql,我觉得我错过了一些明显的东西。我将ID存储为[String],希望能够解析为它们所表示的完整对象 出身背景 这就是我想要启用的。缺少的成分是分解器: const mapIdsToBooks = ({ books }) => books.map(id => fetchBookById(id)) const resolvers = { Author: { books: mapIdsToBooks, }, Library: { books: mapIdsToB

我觉得我错过了一些明显的东西。我将ID存储为
[String]
,希望能够解析为它们所表示的完整对象

出身背景 这就是我想要启用的。缺少的成分是分解器:

const mapIdsToBooks = ({ books }) => books.map(id => fetchBookById(id))

const resolvers = {
  Author: {
    books: mapIdsToBooks,
  },
  Library: {
    books: mapIdsToBooks,
  }
}
const书店=`
打字机{
id:id!
书籍:[书籍]
}
打字簿{
id:id!
标题:字符串
}
类型查询{
getAuthor(id:id!):Author
}
`;
const my_查询=`
质疑{
getAuthor(id:1){
书籍{/*fetchToJson(`/some/external/api/${id}`),
};
我试过的 此解析器不执行任何操作,
console.log
甚至不会被调用

const resolve={
书(…args){
console.log(args);
}
}
然而,这确实得到了一些结果

const resolve = {
  Book: {
    id(id) {
      console.log(id)
      return id;
    }
  }
}
这里的
console.log
确实发出
'a'
'b'
。但我显然无法将其扩展到X个字段,这太荒谬了

我的团队目前所做的是从家长那里解决这个问题:

const resolve={
作者:{
books:({books})=>books.map(id=>fetchBookById(id)),
}
}
这并不理想,因为我可能有一个
类型的出版商{books:[Book]}
类型的用户{favoriteBooks:[Book]}
类型的书店{newBooks:[Book]}
。在每种情况下,引擎盖下的数据实际上都是
[String]
,我不希望必须重复此代码:

const resolve={
X:{
books:({books})=>books.map(id=>fetchBookById(id)),
}
};
定义
Book.id
resolver导致console.log实际触发的事实让我认为这应该是可能的,但我没有在网上任何地方找到我的答案,这似乎是一个非常常见的用例,但我没有在任何地方找到实现细节

我所调查的
  • 模式指令要得到我想要的东西似乎太过分了,我只想能够在数据中实际存在
    [String]
    的任何地方插入
    [Books]@rest('/external/api')
  • 模式委托。在我的用例中,使书籍公开可查询并不真正合适,只是用未使用的查询将我的公共模式弄乱了

感谢您阅读本文。希望我忽略了一个简单的解决方案。如果没有,那么GQL为什么会这样…

如果有帮助,您可以这样想:类型描述响应中返回的数据类型,而字段描述数据的实际值。记住这一点,只有字段才能有解析程序(也就是说,一个函数告诉它要解析到哪种类型的值)。类型的解析器在GraphQL中没有意义

因此,您可以:

1.处理重复。即使你有十种不同的类型,它们都有一个
books
字段,需要以相同的方式进行解析,也不一定是什么大问题。显然,在生产应用程序中,你不会将数据存储在变量中,你的代码可能会更复杂。然而,常见的可以很容易地将逻辑提取到可跨多个解析器重用的函数中:

const mapIdsToBooks = ({ books }) => books.map(id => fetchBookById(id))

const resolvers = {
  Author: {
    books: mapIdsToBooks,
  },
  Library: {
    books: mapIdsToBooks,
  }
}
2.取而代之的是在根级别获取所有数据。您可以在
getAuthor
解析程序中返回作者及其书籍,而不是为
books
字段编写单独的解析程序:

function resolve(root, args) {
  const author = REAL_AUTHOR_DATA.find(row => row.id === args.id)
  if (!author) {
    return null
  }
  return {
    ...author,
    books: author.books.map(id => fetchBookById(id)),
  }
}
在处理数据库时,这通常是一种更好的方法,因为它减少了对数据库的请求数量。但是,如果您正在包装现有的API(这听起来像是您正在做的),那么通过这种方法您将不会真正获得任何好处