简体   繁体   English

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

[英]Context not being passed to nested Apollo GraphQL resolver

I am using Apollo Server v2 for my project 我正在为我的项目使用Apollo Server v2

I have added auth like given here https://www.apollographql.com/docs/apollo-server/features/authentication/ 我添加了auth,就像这里给出的https://www.apollographql.com/docs/apollo-server/features/authentication/

I wanted to include nested resolver in my Query and Mutation so I did as per https://stackoverflow.com/a/40916089/7584077 我想在我的QueryMutation包含嵌套的解析器,所以我按照https://stackoverflow.com/a/40916089/7584077进行了操作

The thing is my resolver is a lil bit more complex than the one shown above 事情是我的解析器比上面显示的更复杂

// 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
  }
`;

And a lil modified version of the stackoverflow answer above. 并且上面的一个lil修改版本的stackoverflow回答。 Here is my combined resolver. 这是我的组合解析器。

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

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

This is because I wanted Query & Mutation to be completely separate. 这是因为我希望QueryMutation完全分开。

Here is my IssueTracker resolver 这是我的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
  }

The thing is here is that, parent actually is the args field! 事情就是这样, parent实际上是args领域! And I need userId from context to make sensible data. 我需要来自上下文的userId来制作合理的数据。

Hmm, the SDL first approach can be a bit tricky. 嗯,SDL的第一种方法可能有点棘手。 It's not easy to explain what is wrong here but I will do my best. 解释这里出了什么问题并不容易,但我会尽力而为。 First let me tell you what to need to do to make this work and then I will explain what goes wrong. 首先让我告诉你需要做些什么来完成这项工作然后我会解释出了什么问题。

Create a IssueTrackerMutation field in the resolver map: 在解析器映射中创建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
  }
};

Note the difference between creating a "pure" resolver for the IssueTracker and returning an object for IssueTracker with a createIssue method. 注意为IssueTracker创建“纯”解析器和使用createIssue方法返回IssueTracker的对象之间的createIssue

Now the function should be called with the expected parameters. 现在应该使用期望的参数调用该函数。 The reason why the parent argument seems to be missing is the very special implementation of the default resolver. 父参数似乎缺失的原因是默认解析器的非常特殊的实现。 The resolver is intended to work with an object oriented style where fields can be fields or methods. 解析器旨在使用面向对象的样式,其中字段可以是字段方法。 You can imagine the resolver to work like this: 您可以想象解析器的工作方式如下:

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];
}

This would allow you to write your data access objects in the following manner: 这将允许您以下列方式编写数据访问对象:

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
  }
};

This is not talked about that much but is probably relatively close how GraphQL at Facebook works. 这并没有被讨论太多,但可能相对接近Facebook的GraphQL如何工作。 The community seems to move more logic into the resolvers. 社区似乎将更多的逻辑转移到解析器中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM