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

news/2024/7/5 17:48:57

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

GraphQL通常被认为是前端的API技术,因为它使客户端能够以更好的方式获取数据。 但是既然是API,当然是在服务器端实现的。 因为GraphQL使服务器开发人员能够专注于描述数据,而不是实现和优化特定的接口,所以在服务器上也有很多好处。

GraphQL执行

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

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每个元素一次:

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 的工具实现上述策略,其他语言也有类似的工具。


http://www.niftyadmin.cn/n/4650853.html

相关文章

python爬虫学习第六章

<!DOCTYPE html>sixth手写python爬虫图片爬虫实战思路 建立一个爬取图片的自定义函数&#xff0c;该函数负责爬取一个页面下的我们想爬取的图片&#xff0c;爬取过程为&#xff1a;首先通过urllib.request.urlopen(url).read()读取对应网页的全部源代码&#xff0c;然后根…

Android入门:广播发送者与广播接收者

参考&#xff1a; Android入门&#xff1a;广播发送者与广播接收者 - xiazdong - CSDN博客http://blog.csdn.net/xiazdong/article/details/7768807 一、广播发送者&广播接收者介绍 1.广播接收者 广播接收者简单地说就是接收广播意图的Java类&#xff0c;此Java类继承Broad…

FINEUI(MVC) grid 双击弹窗功能

添加步骤&#xff1a; 一&#xff0c; 在grid 控件下添加双击的监听 代码 &#xff08;此为客户端代码&#xff09; .Listener("rowdblclick", "onGridRowDblClick") 二&#xff0c; 预先准备弹窗窗体 初始状态为隐藏 其代码如下&#xff1a; (F.Window…

《数据虚拟化:商务智能系统的数据架构与管理》一 2.7 提取-转换-装载、提取-装载-转换和复制...

2.7 提取-转换-装载、提取-装载-转换和复制 从生产数据库获取数据至多种数据存储&#xff0c;数据必然被复制。例如&#xff0c;数据需要从生产数据库复制到数据中转区或者ODS&#xff0c;从ODS到数据仓库&#xff0c;从数据仓库到数据集市&#xff0c;等等。然而&#xff0c;…

es6基础() ={}

function name(params) {} es6中的写法 () >{} 转载于:https://www.cnblogs.com/phermis/p/8280163.html

对于Java对象的几点疑惑解答

1 直接输出一个类的对象 众所周知&#xff0c;我们创建一个对象后&#xff0c;可以利用print()方法把该对象的属性给输出&#xff0c;但是我们若直接输出对象呢&#xff1f;比如下例&#xff1a; 1 class People {2 String name;3 int age;4 }5 6 public class Main {…

图像检索-乘积量化

参考链接&#xff1a;https://blog.csdn.net/guanyonglai/article/details/78468673 看了两天的乘积量化&#xff0c;先说下我自己的理解吧&#xff1a;&#xff08;以下蓝字使我的理解&#xff0c;红字是我看别人的博客暂时没弄懂的&#xff0c;我写的比较啰嗦以便我回头自己翻…

ubuntu16.04安装hustoj

安装hustoj需要lamp环境。 前提工作&#xff1a; 更新软件库&#xff1a; sudo apt update 更新全部软件: sudo apt upgrade &#xff08;一&#xff09;安装mysql5.7&#xff1a; sudo apt-get install mysql-server mysql-client 安装过程中会弹出框来让你设置密码&#xff…