代码之家  ›  专栏  ›  技术社区  ›  THpubs

如何从服务器加载graphql查询而不在前端定义它?

  •  1
  • THpubs  · 技术社区  · 8 年前

    现在假设我们使用的是restapi。我有这样一个端点: /homeNewsFeed

    [
      {
        blockTitle: 'News',
        type: 'list',
        api: 'http://localhost/news'
      },
      {
        blockTitle: 'Photos',
        type: 'gallery',
        api: 'http://localhost/gallery'
      }
    ]
    

    现在在得到这个之后,我们遍历数组并调用相应的端点来加载数据。我的问题是,如何在GraphQL中实现这一点?通常我们在前端代码中定义查询。如果不这样做,如何让服务器决定发送什么?

    1 回复  |  直到 8 年前
        1
  •  4
  •   Daniel Rearden    7 年前

    通常我们在前端代码中定义查询。如果不这样做,如何让服务器决定发送什么?

    spec ,GraphQL执行请求必须包括两个部分:1)模式;以及2)包含操作定义的文档。操作定义确定要执行的操作(哪个查询或变异)以及响应的格式。有变通方法和例外(我将在下面讨论一些),但是,一般来说, 如果指定客户端上的响应的形状是不可取的或某种不可能的,那么您应该仔细考虑GraphQL是否是您需要的正确解决方案。

    除此之外,GraphQL更适合于单个请求,而不是现有restapi所需的一系列结构化请求。所以答案看起来更像这样:

    [
      {
        title: 'News',
        content: [
          ...
        ],
      },
      {
        title: 'Photos',
        content: [
          ...
        ],
      }
    ]
    

    相应的查询可能如下所示:

    query HomePageContent {
      blocks {
        title
        content {
          # additional fields
        }
      }
    }
    

    content . 这通常通过使用接口或联合将多个类型聚合为单个抽象类型来解决。模式的确切结构将取决于您发送的数据,但下面是一个示例:

    interface BlockContentItem {
      id: ID!
      url: String!
    }
    
    type Story implements BlockContentItem {
      id: ID!
      url: String!
      author: String!
      title: String! 
    }
    
    type Image implement BlockContentItem {
      id: ID!
      url: String!
      alt: String!
    }
    
    type Block {
      title: String!
      content: [BlockContentItem!]!
    }
    
    type Query {
      blocks: [Block!]!
    }
    

    您现在可以查询 blocks

    query HomePageContent {
      blocks {
        title
        content {
          # these fields apply to all BlockContentItems
          __typename
          id
          url
          # then we use inline fragments to specify type-specific fields
          ... on Image {
            alt
          }
          ... on Story {
            author
            title
          }
        }
      }
    }
    

    __typename 识别给定对象的类型,这可能对客户端应用程序有帮助(像Apollo这样的客户端会自动包含此字段)。

    当然,当您想添加一个新的块时,仍然有一个问题。如果块的内容符合现有类型,则无需担心。但是,如果你预期将来需要一种不同的类型,但现在却不能围绕着它进行设计,会发生什么呢?

    通常,这种更改需要服务器上的模式更改和客户端上的查询更改。而且在 ,这可能很好,因为如果您使用不同的结构获取数据, . 否则,您的应用程序将不知道如何正确呈现新的数据结构。

    1. 而不是为 内容 ,只需使用自定义的JSON标量。这将有效地抛出响应验证窗口,但它将允许您为给定块的内容返回所需的任何内容。

    2. 将将来可能需要的任何字段抽象为某种值键类型。例如:

    type MetaItem {
      key: String!
      value: String!
    }
    
    type Block {
      title: String!
      meta: [MetaItem!]!
      # other common fields
    }
    

    推荐文章