gpt4 book ai didi

graphql - buildSchema 和 GraphQLSchema 之间的显着差异?

转载 作者:行者123 更新时间:2023-12-04 02:45:01 24 4
gpt4 key购买 nike

两者之间有什么显着差异吗?我对从运行时和启动性能到功能和工作流程差异的任何事情都感兴趣。文档在解释差异以及何时应该使用一个而不是另一个方面做得很差。

两个版本中的示例:

构建架构

const { graphql, buildSchema } = require('graphql');

const schema = buildSchema(`
type Query {
hello: String
}
`);

const root = { hello: () => 'Hello world!' };

graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});

GraphQLSchema

const { graphql, GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql');

const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
hello: {
type: GraphQLString,
resolve: () => 'Hello world!'
}
})
})
});

graphql(schema, '{ hello }').then((response) => {
console.log(response);
});

最佳答案

buildSchema函数采用 SDL(模式定义语言)中的模式并返回 GraphQLSchema目的。给定使用每种方法生成的两个相同模式,运行时性能将相同。使用 buildSchema 的服务器的启动时间会更慢,因为解析 SDL 增加了一个原本不存在的额外步骤——是否会有明显的差异,我不能肯定地说。

使用 buildSchema通常是不可取的,因为它严重限制了架构的功能。

使用 buildSchema 生成的模式:

  • 无法为单个字段指定解析函数
  • 不能指定 resolveTypeisTypeOf类型的属性,使其无法使用 UnionsInterfaces
  • 不能使用自定义标量

  • 第 1 项的压力不够- buildSchema不允许您为架构中的任何字段指定解析器函数。这包括您 Query 上的字段和 Mutation类型。使用 buildSchema 的示例通过依赖 GraphQL 的默认解析器行为并传入 root 来解决这个问题。值(value)。

    默认情况下,如果字段没有 resolve函数指定,GraphQL 将检查父值(由父字段的解析器返回)并且(假设它是一个对象)将尝试在该父值上找到与字段名称匹配的属性。如果找到匹配项,则将该字段解析为该值。如果匹配恰好是一个函数,它首先调用该函数,然后解析为该函数返回的值。

    在上面的例子中, hello第一个模式中的字段没有解析器。 GraphQL 查看父值,对于根级别字段,它是传入的根值。根值有一个名为 hello 的字段。 ,并且它是一个函数,因此它调用该函数,然后解析为该函数返回的值。您只需制作 hello 即可达到相同的效果。属性也是一个字符串而不是一个函数。

    综上所述,题中的两个例子其实是 不是 相同。相反,我们必须像这样修改第二个模式以使其等效:
    const schema = new GraphQLSchema({
    query: new GraphQLObjectType({
    name: 'Query',
    fields: () => ({
    hello: {
    type: GraphQLString,
    }
    })
    })
    });

    const root = { hello: () => 'Hello world!' };

    graphql(schema, '{ hello }', root).then((response) => {
    console.log(response);
    });

    虽然通过根传递解析器是一个巧妙的技巧,但它同样只适用于根级字段(如 QueryMutationSubscription 类型上的字段)。如果您想为不同类型的字段提供解析器,则无法使用 buildSchema 来实现。 .

    底线:不要使用 buildSchema .

    但我想使用 SDL!

    你仍然可以!但是...不要使用 vanilla GraphQL.js 来做。相反,如果您想利用 SDL 来生成您的架构,您应该改为使用 graphql-tools ' makeExecutableSchema或者使用更完整的解决方案,如 apollo-server , 使用 makeExecutableSchema在引擎盖下。 makeExecutableSchema允许您使用 SDL 定义模式,同时还提供单独的 resolvers目的。所以你可以这样做:
    const typeDefs = `
    type Query {
    hello: String
    }
    `

    const resolvers = {
    Query: {
    hello: () => 'Hello!',
    },
    }

    const schema = makeExecutableSchema({ typeDefs, resolvers })

    不同的是,不像 buildSchema ,你也可以提供其他类型的解析器,甚至可以提供 resolveType接口(interface)或联合的属性。
    const resolvers = {
    Query: {
    animals: () => getAnimalsFromDB(),
    }
    Animal: {
    __resolveType: (obj) => obj.constructor.name
    },
    Cat: {
    owner: (cat) => getOwnerFromDB(cat.ownerId),
    }
    }

    使用 makeExecutableSchema ,您还可以实现自定义标量和模式指令,轻松自定义各种模式验证规则,甚至允许实现类型从其接口(interface)继承解析器。虽然了解 GraphQL.js 的基础知识以及如何使用 GraphQLSchema 生成基本模式至关重要。构造函数, makeExecutableSchema是一个更完整、更灵活的解决方案,应该是大多数项目的首选。 See the docs更多细节。

    更新

    如果您一心想使用 buildSchema ,实际上可以通过使用 ES6 类来解决无法为非根类型提供解析器的问题。退房 this sample schema .这并没有解决 buildSchema 的所有其他限制,但它确实使它更可口。

    关于graphql - buildSchema 和 GraphQLSchema 之间的显着差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53984094/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com