[译] 怎样使用GraphQL - 进阶 - 2.服务端

英文原版地址:https://www.howtographql.com/...前端

GraphQL一般被认为是前端的API技术,由于它使客户端可以以更好的方式获取数据。 可是既然是API,固然是在服务器端实现的。 由于GraphQL使服务器开发人员可以专一于描述数据,而不是实现和优化特定的接口,因此在服务器上也有不少好处。git

GraphQL执行

GraphQL经过定义Schema和查询语言,来从Schema中检索数据,但却不只仅是这一种方式。更是一种实际的执行算法,用于将这些查询转换为结果。 该算法的核心很是简单:查询逐字段遍历,为每一个字段执行“解析器”。 让假设咱们有如下模式:github

type Query {
  author(id: ID!): [Author]
}

type Author {
  posts: [Post]
}

type Post {
  title: String
  content: String
}

下面是咱们使用该Schema发送到服务器的查询:算法

query {
  author(id: "abc") {
    posts {
      title
      content
    }
  }
}

首先要关注的是查询中的每一个字段均可以与一个类型相对应:数据库

query: Query {
  author(id: "abc"): Author {
    posts: [Post] {
      title: String
      content: String
    }
  }
}

如今,咱们能够轻松地找到并运行服务器中每一个字段对应的解析器。从查询类型开始执行,并之外层为先。这意味着咱们先运行Query.author的解析器。而后,咱们将该解析器的结果传递给它的子解析器,Author.posts的解析器。在下一级,结果是一个列表,在这种状况下,算法会依次在每一个元素上执行一次。因此最终执行工做以下:后端

Query.author(root, { id: 'abc' }, context) -> author
Author.posts(author, null, context) -> posts
for each post in posts
  Post.title(post, null, context) -> title
  Post.content(post, null, context) -> content

最终,执行算法将全部结果数据正确的放在定义好的结构中,并返回。
须要注意的是,大多数GraphQL服务器实现将提供“默认解析器” - 所以您没必要为每一个单个字段指定解析器函数。例如,在GraphQL.js中,当解析器的父对象包含具备正确名称的字段时,不须要指定解析器。
在Apollo博客上的“GraphQL Explained“文章中,可更深刻的了解GraphQL执行状况。服务器

批量解析

你可能会注意到上述执行策略的一件事是,它有点幼稚。例如,若是你有从后端API或数据库提取的解析器,则在执行一个查询期间可能会屡次调用该后端。让咱们假设,咱们想获取几个帖子的做者,就像这样:函数

query {
  posts {
    title
    author {
      name
      avatar
    }
  }
}

若是这些是博客上的帖子,极可能不少帖子将有相同的做者。因此若是咱们须要一个API调用来获取每一个做者对象,咱们可能会意外地为同一个对象发出多个请求。例如:工具

fetch('/authors/1')
fetch('/authors/2')
fetch('/authors/1')
fetch('/authors/2')
fetch('/authors/1')
fetch('/authors/2')

咱们如何解决这个问题?让咱们聪明一点。咱们能够将fetch函数封装在一个工具函数中,该实函数将等待全部的解析器运行后,再确保只fetch每一个元素一次:post

authorLoader = new AuthorLoader()

// Queue up a bunch of fetches
authorLoader.load(1);
authorLoader.load(2);
authorLoader.load(1);
authorLoader.load(2);

// Then, the loader only does the minimal amount of work
fetch('/authors/1');
fetch('/authors/2');

咱们能作得更好吗?固然,若是咱们的API支持批量请求,咱们只能对后端执行一次提取操做,以下所示:

fetch('/authors?ids=1,2')

这也能够封装在上面的工具函数中。
在JavaScript中,可使用 DataLoader 的工具实现上述策略,其余语言也有相似的工具。

相关文章
相关标签/搜索