上下文未传递给嵌套的 Apollo GraphQL 解析器

Posted

技术标签:

【中文标题】上下文未传递给嵌套的 Apollo GraphQL 解析器【英文标题】:Context not being passed to nested Apollo GraphQL resolver 【发布时间】:2019-11-06 13:12:36 【问题描述】:

我正在为我的项目使用 Apollo Server v2

我已经添加了像这里给出的身份验证https://www.apollographql.com/docs/apollo-server/features/authentication/

我想在我的QueryMutation 中包含嵌套解析器,所以我按照https://***.com/a/40916089/7584077 做了

问题是我的解析器比上面显示的要复杂一点

// typeDefs/typeDefs.js
import  gql  from "apollo-server-express";
import issueTracker from "./issueTracker";

const base = gql`
  scalar Timestamp

  type Query 
    ping: String!
  

  type Mutation 
    ping: String!
  
`;

export default [base, issueTracker];
// typeDefs/issuetracker.js
import  gql  from "apollo-server-express";

export default gql`
  type Comment 
    id: ID
    message: String
    commentBy: User
    createdAt: Timestamp
    updatedAt: Timestamp
    version: Int
  

  type Issue 
    id: ID
    requestId: ID
    title: String
    issueNumber: Int
    status: Int
    tags: [String]
    assignees: [User]
    createdBy: User
    comments: [Comment]
    createdAt: Timestamp
    updatedAt: Timestamp
    version: Int
  

  input CreateIssueRequest 
    requestId: ID!
    title: String!
    createdBy: ID!
    message: String!
    assignees: [ID]!
  

  type IssueTrackerQuery 
    ping: String!
  

  type IssueTrackerMutation 
    createIssue(request: CreateIssueRequest!): Issue
  

  extend type Query 
    IssueTracker: IssueTrackerQuery
  

  extend type Mutation 
    IssueTracker: IssueTrackerMutation
  
`;

以及上面 *** 答案的 lil 修改版本。 这是我的组合解析器。

// resolvers/resolvers.js
import IssueTracker from "./issueTracker";

export default 
  Query: 
    ping: () => "ping!",
    IssueTracker: () => (
      ping: IssueTracker.ping,
    ),
  ,
  Mutation: 
    ping: () => "ping!",
    IssueTracker: () => (
      createIssue: IssueTracker.createIssue,
    ),
  ,
;

这是因为我希望 QueryMutation 完全分开。

这是我的 IssueTracker 解析器

// resolvers/issueTracker.js
export default 
  ping: () => "ping",
  createIssue: async (parent, args, context) => 
    console.log(parent);
    console.log(args);
    console.log(context);
    // create issue as per request and return
  

问题在于,parent 实际上是 args 字段! 而且我需要上下文中的 userId 来制作合理的数据。

【问题讨论】:

【参考方案1】:

嗯,SDL 第一种方法可能有点棘手。解释这里出了什么问题并不容易,但我会尽力而为。首先让我告诉你需要做些什么来完成这项工作,然后我会解释哪里出了问题。

在解析器映射中创建一个IssueTrackerMutation 字段:

export default 
  Query: 
    ping: () => "ping!",
    IssueTracker: () => ( // same here but I will just do the mutation for you
      ping: IssueTracker.ping,
    ),
  ,
  Mutation: 
    ping: () => "ping!",
    IssueTracker: () => null, // or whatever you want as a root here
  ,
  IssueTrackerMutation: 
    createIssue: IssueTracker.createIssue
  
;

请注意为 IssueTracker 创建“纯”解析器与使用 createIssue 方法为 IssueTracker 返回对象之间的区别。

现在应该使用预期的参数调用该函数。似乎缺少 parent 参数的原因是默认解析器的非常特殊的实现。解析器旨在使用面向对象的样式,其中字段可以是字段方法。你可以想象解析器是这样工作的:

defaultResolver(fieldName, parent, args, context, info) 
  if (typeof parent !== 'object') 
    throw "Need object to default resolve";
  
  if (typeof parent[fieldName] === 'function') 
    return parent[fieldName](args, context, info);
  
  return parent[fieldName];

这将允许您以下列方式编写数据访问对象:

class IssueTracker 
  issues = []
  async createIssue(args, ctx, info) 
    const issue = await createIssue(args.request);
    this.issues.push(issue);
    return issue;
  


const issueTracker = new IssueTracker();

export default 
  // ...
  Mutation: 
    // ...
    IssueTracker: () => issueTracker,
  ,
  IssueTrackerMutation: 
    createIssue: IssueTracker.createIssue
  
;

这没有太多讨论,但可能与 Facebook 的 GraphQL 工作方式比较接近。社区似乎将更多逻辑转移到解析器中。

【讨论】:

以上是关于上下文未传递给嵌套的 Apollo GraphQL 解析器的主要内容,如果未能解决你的问题,请参考以下文章

React + Apollo:GraphQL 错误数组未传递到组件中

如何在反应js中将graphql列表传递给apollo中的突变

将 ownProps 传递给 Apollo graphql 包装的组件

Graphql,react-apollo如何在加载组件状态时将变量传递给查询

使用 graphql 将道具传递给高阶组件时出现 React-apollo Typescript 错误

React Native、GraphQL、Apollo - 如何创建批量插入突变