graphql中resolver函数的不同实现说明

2024-02-24

我一直在阅读 graphQL 文档,发现他们以两种方式解释了 graphql 服务器的实现:一种使用 graphql-yoga,这是一个功能齐全的 graphql 服务器,另一种是使用 graphql、express-graphql 和express 。在这两种情况下,我们在创建服务器实例时传递架构和解析器函数。

但解析器函数的实现有所不同。使用 graphql-yoga 时,解析器函数提供了 4 个参数,其中包含有关父对象、收到的参数、上下文、信息的信息。而在另一种情况下(使用 graphql),解析器函数仅获取参数对象。

为什么 ?如果我想要信息、上下文对象,我如何获取它?

使用 graphql-yoga 示例:https://graphql.org/learn/execution/ https://graphql.org/learn/execution/

使用 graphql 示例:https://graphql.github.io/graphql-js/mutations-and-input-types/ https://graphql.github.io/graphql-js/mutations-and-input-types/

// 使用 graphql 的代码示例

var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var schema = buildSchema(`
type Query {
    rollDice(numDice: Int!, numSides: Int): [Int]
}
type Mutation {
    addDice(numDice: Int): String
}
`);

var root = {
    rollDice({numDice, numSides}) {
        return [1, 2];
    },
    addDice({numDice}) {
        console.log("Adding something");
        return "Added";
    }
};

var app = express();
app.use('/graphql', graphqlHTTP({
    schema: schema,
    rootValue: root,
    graphiql: true,
}));
app.listen(4000);
console.log('Running a GraphQL API server at localhost:4000/graphql');

// 使用 graphql-yoga 的代码示例

let graphqlServer = require("graphql-yoga");

const typeDefs = `
    type Query {
        rollDice(numDice: Int!, numSides: Int): [Int]
    }
    type Mutation {
        addDice(numDice: Int): String
    }
    `;

const resolvers = {
    Query: {
        rollDice(parent, args, context, info) {
            console.log(args.numDice);
            console.log(args.numSides);
            return [1, 2];
        }
    },
    Mutation: {
        addDice(parent, args, context, info) {
            console.log(args.numDice);
            return "Added";
        }
    }
};

const server = new graphqlServer.GraphQLServer({
    typeDefs,
    resolvers
});

server.start(() => {
    console.log("server started on localhost:4000");
});

这两个代码片段之间的区别:

在一种情况下,解析器函数存在于适当的类型(即查询、突变)内。在另一种情况下,它们存在于一个根对象内。这意味着在第一种情况下,我可以在查询和突变中使用相同名称的方法,而在第二种情况下,这是不可能的,因为它们是单个对象的键,并且键应该是唯一的。

为什么会这样呢?我基本上错过了什么吗?一个包与另一个包的实现细节有何不同?


真正的谈话:GraphQL.js 文档不是那么好。在我看来,他们永远不应该使用示例buildSchema首先,因为它会导致这种混乱,这是可以理解的。

GraphQL.js(即graphqlpackage) 是 GraphQL 的 JavaScript 实现。在 GraphQL.js 中构建模式是通过构建一个实例以编程方式完成的GraphQLSchema class:

const userType = new GraphQLObjectType({
  name: 'User',
  fields: {
    id: {
      type: GraphQLID,
    },
    email: {
      type: GraphQLString,
    },
  },
});
const queryType = new GraphQLObjectType({
  name: 'Query',
  fields: {
    user: {
      type: userType,
      resolve: () => ({ id: 1, email: '[email protected] /cdn-cgi/l/email-protection' }),
    },
  },
});
const schema = new GraphQLSchema({
  query: queryType,
})

如果我们用模式定义语言(SDL)打印这个模式,它看起来像这样:

type Query {
  user: User
}

type User {
  id: ID
  email: String
}

使用 SDL 比编写所有代码要容易得多。但是,GraphQL.js 不提供从 SDL 构建功能齐全的架构的方法。 It does提供一个buildSchema函数,但是这个实用程序构建了一个模式没有任何解析器(以及许多其他功能,例如联合/接口类型解析)。

The graphql-tools包提供了一个makeExecutableSchema函数允许您从 SDL 和解析器映射对象构建架构。这是在幕后使用的apollo-server and graphql-yoga. makeExecutableSchema使用 SDL 构造模式buildSchema然后改变结果对象,添加解析器事后 https://github.com/apollographql/graphql-tools/blob/master/src/generate/addResolveFunctionsToSchema.ts.

在 GraphQL.js 中,resolve字段的函数(或解析器)有四个参数——父值、字段的参数、上下文和GraphQLResolveInfo目的。如果我们要创建一个GraphQLObjectType like userType在上面的示例中,这是我们可以为对象中的每个字段提供的可选函数。这是same您在构造解析器映射时定义的函数以供使用graphql-yoga. 这是字段解析器的唯一实现。

那么这是怎么回事buildSchema??

文档中的示例利用了 GraphQL默认字段解析器 https://github.com/graphql/graphql-js/blob/86f6e821c803d7f1e22a99d7d22aab63c6c9f957/src/execution/execute.js#L1238:

export const defaultFieldResolver: GraphQLFieldResolver<any, *> = function(
  source,
  args,
  contextValue,
  info,
) {
  if (typeof source === 'object' || typeof source === 'function') {
    const property = source[info.fieldName];
    if (typeof property === 'function') {
      return source[info.fieldName](args, contextValue, info);
    }
    return property;
  }
};

如您所见,默认解析逻辑会查找与源(父)值上的字段同名的属性。在我们上面的例子中,user解析器返回{id: 1, email: '[email protected] /cdn-cgi/l/email-protection'}-- 这是该字段的值resolves到。该字段的类型为User。我们没有为我们定义解析器id字段,因此默认解析器会执行其操作。这id字段解析为1因为这是名为的属性的值id在解析器接收的父对象上。

然而,父值可以also是一个函数而不是一个对象。如果它是一个函数,则首先调用它,然后使用返回值。该函数是用什么来调用的?好吧,它不能向它传递父值(因为无限递归),但它can向其传递剩余的三个参数(args、context 和 info)。这就是它的作用。

现在来看看魔术 ????????

在我们的示例中,我可以省略解析器user字段并将函数传递给根值。

const root = {
  user: () => ({id: 1, email: '[email protected] /cdn-cgi/l/email-protection'})
}

根对象只是一个可选对象,它作为父值传递给根级别的解析器(就像您的Query or Mutation类型)。否则,这些解析器将没有父值。

Query是一种操作根类型——它充当架构其余部分的“入口点”。上的任何字段Querytype 将作为父值传递给根对象。如果我省略了解析器user字段,默认解析器将 1) 检查父对象是否有同名的属性,2) 查找属性并确定它是一个函数,3) 调用该函数,4) 将字段解析为函数的返回值。

TADA!

但是,由于该函数是由默认解析器调用的,并且本身不用作解析器,因此它只会接收上述三个参数,而不是 4 个。

这是解决无法解决问题的巧妙方法actually为模式提供自定义解析器,但它非常有限。它仅适用于根类型,因此我们不能类似地为User字段或其他类型。我们不能在模式中使用接口或联合,因为我们无法提供resolveType功能。等等...

希望这能提供一些清晰度。希望我们能够在不久的将来更新文档,以避免所有这些混乱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

graphql中resolver函数的不同实现说明 的相关文章

随机推荐

  • 由于用户数据脚本,AWS 自动缩放启动未就绪的实例

    我有一个运行良好的自动缩放功能 带有一个启动配置 其中我定义了一个在新实例启动时执行的用户数据脚本 用户脚本更新基本代码并生成缓存 这需要几秒钟的时间 但是 一旦实例 创建 而不是 准备就绪 自动缩放就会将其添加到负载均衡器中 这是一个问题
  • 在现有 ASP.NET WebForms 站点中添加带有根路径的第二语言支持

    我继承了一个非常小的 ASP NET WebForms 项目 我的客户希望为其添加第二种语言 对于每个 somepage aspx 我想支持它的 第二语言路径 版本 例如 fr somepage aspx 我想使用正常的全球化 两种语言的
  • github.io 阻止了 ajax 请求

    我所有带有ajax请求的应用程序都返回错误 此请求已被阻止 内容必须通过 HTTPS 提供 例如 https zzharuk github io local weather widget https zzharuk github io lo
  • 在运行时合并两个程序集 - C#

    是否可以在运行时合并两个程序集 以便在迭代 ExportedTypes 时返回两个原始程序集中的所有类型 The why 我使用数据库迁移框架来更新我的数据库 它采用由特殊类组成的单个程序集 用于定义对数据库所做的修改 我有两个非常相似的数
  • 使用 git stash 时的 sh.exe.stackdump

    我是 Git 新手 对 stash 命令有疑问 当我编写 git stash git stash list git stash apply git drop 等命令时 我总是得到一个名为 sh exe stackdump 的文件 Excep
  • 带参数的 REST GET 动词

    我正在和我的队友一起阅读一些 REST 我们正在编写一个 RoR 应用程序 它将向世界其他地方公开它的一些功能 我在这个团队的任务是制作一个公开日记报告的资源 如果你打电话 http root com journalreports http
  • 如何确保curl 使用openssl,而不是nss?

    是否可以通过配置来保证parameter http curl haxx se docs manpage html that curl uses OpenSSL http www openssl org and not NSS http ww
  • 在 codeigniter 中启用 $_GET

    我一直在试图弄清楚如何在 CI 中启用 GET 看起来框架故意破坏了 GET 数组 并且启用它需要对核心类进行认真的修改 谁能说出这是为什么 以及如何克服它 请注意 我希望保持 URI 解析和路由的方式不变 只需让 GET 也可用即可 将以
  • Django - 使用 templatetags 渲染许多模板非常慢

    假设 我有一个带有照片库的页面 每个缩略图都有例如照片 国家 地区 作者等 我使用模板标签 加载指定的模板 渲染这些项目 小部件 由于 DRY 我在页面上的不同位置单独使用这些项目 小部件 所以会这样 而且速度非常慢 我使用 django
  • 如何使按钮可重复使用?

    我对编程世界还比较陌生 我对 HTML 和 CSS 有扎实的了解 最近又学习了 JavaScript 我正在开发一系列文本生成器作为学校项目 我的目标是能够在网站上单击一个按钮 并让计算机在每次单击该按钮时吐出随机文本 然而 虽然我对 HT
  • 在 httpContextAccessor.HttpContext 上返回 null

    我们重写 SaveChangesAsync 以自动更新 DateCreated CreatedBy LastDateModified 和 LastModifiedBy 对于CreatedBy和LastModifiedBt 我们需要Ident
  • 获取 Android Google Analytics 引荐来源网址标签

    我们计划使用 Google Analytics 来跟踪通过 Android Market 到我们的应用程序的广告点击推荐 根据谷歌文档 http code google com apis analytics docs mobile andr
  • 带有自定义标头的 Resttemplate GET 请求

    我需要发送带有标头的 GET 请求 Content Type application camiant msr v2 0 xml 我期望来自服务器的 XML 响应 我用 Postman 测试了请求和响应 一切都很好 但是当我尝试在春天这样做时
  • 密码哈希 PHP 7 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我目前正在学习 PHP 并且一直在论坛中查找有关如何最好地在 PHP 中对密码进行哈希处理的最新想法 任何人都可以建议目前最好使用的密码哈希方法
  • JSON 嵌套在 POJO 中

    我有一个 POJO 类 public class D private JSONObject profileData public JSONObject getProfileData return profileData public voi
  • 如何在 Eclipse Juno 中打开 OSGi 控制台?

    eclipse console 上面的命令在不同的窗口中打开 OSGi 控制台和 Eclipse IDE 是否有任何选项可以将 OSGi 控制台引入 Eclipse 的控制台视图中 您只需选择 主机 OSGi 控制台 http archiv
  • 使用 JUnit 进行单元测试时如何处理异常?

    如果一个方法抛出异常 如何编写测试用例来验证该方法实际上抛出了预期的异常 在最新版本的 JUnit 中 它是这样工作的 import org junit Rule import org junit Test import org junit
  • 迭代多维关联数组 PHP 中的每个键和值

    我刚刚了解了键 值对 我尝试寻找现有的答案 并尝试了解有关键 值对和关联数组的知识 尽管这有点太耗时了 我很难弄清楚如何迭代这个多维关联数组而不出现任何错误 arr array test1 gt array testing 1 1 gt a
  • 使用索引和列作为 X、Y 以及值作为 Z 将 pandas DataFrame 转换为 3D 图表?

    我正在尝试使用 Pandas Dataframe 创建 3d 波动性表面 我觉得我拥有所有信息 但我不确定如何从中创建 3d 图表 我读过的每本指南似乎都使用 3 个独立的数组 但我觉得我拥有的数据应该是可图形化的 我当前的数据框如下所示
  • graphql中resolver函数的不同实现说明

    我一直在阅读 graphQL 文档 发现他们以两种方式解释了 graphql 服务器的实现 一种使用 graphql yoga 这是一个功能齐全的 graphql 服务器 另一种是使用 graphql express graphql 和ex