express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值

Posted

技术标签:

【中文标题】express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值【英文标题】:express-graphql resolver args is empty in resolver but info variableValues populated with name and value 【发布时间】:2019-09-06 19:02:01 【问题描述】:

使用apollo-server-expressgraphql-tools,我正在尝试从JSON 对象创建一个最小可行的架构:

const books = [
  
    "title": "Harry Potter",
    "author": 'J.K. Rowling',
    "slug": "harry_potter",
  ,
  
    "title": 'Jurassic Park',
    "author": 'Michael Crichton',
    "slug": "jurassic_park",
  ,
];

// The GraphQL schema in string form
const typeDefs = `
  type Query 
    books: [Book]
    book(title: String!): Book
  
  type Book  title: String!, author: String!, slug: String! 
`;

// The resolvers
const resolvers = 
  Query: 
    books: () => books,
    book: (_,  title ) => books.filter(book => 
      return new Promise((resolve, reject) => 
        if(book.title == title) 
          console.log('hack log resolve book _: ', JSON.stringify(book))
          resolve(JSON.stringify(book));
        
      )
    ),
   ,
   Book: 
     title: (root, args, context, info) => 
       //args is empty, need to match arg w book.title
       /*
       context:  
        _extensionStack:
         GraphQLExtensionStack 
           extensions: [ [FormatErrorExtension], [CacheControlExtension] ]
         
       
       , root,
       */
       console.log('resolve Book args: ', args, 'info', info);//JSON.stringify(root.book))
       return books.filter(book => 
         if(book.title == root.title) 
           return book;
         
       );//JSON.stringify("title": root.title);
     
   
;
//    book: (_,  title ) => books.filter(book => book.title == title),


// Put together a schema
const schema = makeExecutableSchema(
  typeDefs,
  resolvers,
);

这是my repository。

当记录和单步执行node_modules/graphql/execution/execute.js 时,执行argsOrSchema.variableValues 的第一个参数包含查询参数键和值,但是第五个参数variableValues 未定义。

根据this GitHub issue等一些线程,我可以从解析器的info参数中提取variableValues,但是我仍然想知道为什么args对象为空?

Here is a gist GraphQL 在解析器函数中给出的信息日志

【问题讨论】:

【参考方案1】:

args 参数由传递给正在解析的字段的参数填充 -- 传递给 其他 字段的任何参数都不会包含在 args 参数中。

您的架构在您的 Query 类型的 book 字段中包含一个参数 (title)。这意味着该字段的解析器将接收 title 参数作为其 args 参数的一部分,但前提是该参数实际上包含在您的查询中:

// Request
query 
  book(title: "Something") 
    title
  


// Resolvers
const resolvers = 
  Query: 
    book: (root, args) => 
      console.log(args) // title: 'Something'
    
  ,

相对于:

// Request
query 
  book 
    title
  


// Resolvers
const resolvers = 
  Query: 
    book: (root, args) => 
      console.log(args) // 
    
  ,

如果您为title 参数传入一个值,那么在解析器中为其他字段获取该值的唯一方法是解析info 参数。您不会查看variableValues 属性,因为传递给参数的值可能是文字值或变量。您需要遍历 fieldNodes 数组并找到适当的参数值。

但是,通常不需要经历所有这些。

如果book 字段应该只返回一个书本对象,则从books 数组中选择正确书籍的逻辑应该包含在该字段的解析器中:

const resolvers = 
  Query: 
    book: (root, args) => 
      return books.find(book => book.title === args.title)
    
  ,

没有理由在 title 类型上包含 title 字段的解析器,除非您需要该字段解析为默认情况下将解析的内容(title 上的属性由父字段的解析器返回的对象)。这足以按标题查询所有书籍和单本书:

const resolvers = 
  Query: 
    book: (root, args) => 
      return books.find(book => book.title === args.title)
    ,
    books: () => books,
  ,

查看来自 Apollo 的 official tutorial 以获取更多示例以及解析器工作原理的完整说明。

【讨论】:

以上是关于express-graphql 解析器参数在解析器中为空,但 info variableValues 填充了名称和值的主要内容,如果未能解决你的问题,请参考以下文章

graphql中解析器函数的不同实现说明

如何在一个类型中添加多个解析器(Apollo-server)

express-graphql:上下文始终未定义

如何使用 express-graphql 引发多个错误?

graphql 为啥我需要在解析器参数中声明一个额外的参数

springboot自定义参数解析器