如何在纯JavaScript中使用GraphQL
作者|布莱恩里纳尔迪
翻译|王强
规划|李俊辰
除了REST,很多API也开始支持GraphQL,甚至完全支持。但是,如果您需要使用一个GraphQL API,您自然会认为您需要使用React和/或其他库来使它运行。这是因为许多教程和示例代码似乎是基于这样的假设,即如果您正在使用GraphQL,您需要使用这些库。
然而,对GraphQL API的查询只是一个定制的HTTP请求。一个GraphQL响应无非就是JSON。不需要用什么精致的库来处理。在本教程中,我想采取一种不同的方法,向您展示从节点和客户端JavaScript(没有库)调用GraphQL API是多么容易。
GraphQL请求的基础
与RESTful API不同,GraphQL只有一个端点。虽然GraphQL可以响应GET请求,但典型的GraphQL HTTP请求是作为POST请求发送的。
您的GraphQL请求可以发送三条数据:查询、操作名和变量。
查询是必需的,包括(你猜对了)GraphQL查询。由于GraphQL通过单个端点运行,端点响应的数据完全取决于您的查询。该查询要求GraphQL格式正确。想知道如何建立查询?请参见关于如何编写GraphQL查询的教程。
https://stepzen.com/blog/how-to-write-graphql-queries
变量是可选的,它是一个JSON对象,包含要传递给查询的所有变量的值。例如,如果您的查询需要一个变量id(在查询中将显示为$id),您需要按如下方式发送该变量:
操作名称也是可选的。当查询包含多个命名操作时,它用于指定要运行的操作。
如果您发送一个GraphQL作为GET请求,您需要将上述内容作为查询参数传递。鉴于GraphQL查询可能会变得很长,这不是最好的选择,我们还是考虑POST请求。在本教程中,我们将介绍我在StepZen上创建的一个简单的Scooby DooAPI,它用于连接到MySQL数据源(StepZen现在处于私有alpha状态,但您可以在此请求访问:
https://stepzen.com/request-invite
GraphQL请求的基础
我们可以通过Node.js发送查询,不需要任何特殊的库,使用标准的Node https库格式化POST请求。让我们看一个不使用特殊库的简单例子(注意,我确实使用了dotenv来获取访问我的StepZen后端的API密钥)。在这个例子中,我只传递了一个查询,在发送之前需要序列化。另外,这是一个相当标准的HTTPPOST。
同样,返回的数据只是JSON,所以如果我们想运行它,控制台中的输出将是:
简化请求
让我们通过使用类似节点提取的东西来简化这个过程,以减少发出HTTP请求所需的样板代码量。节点获取库在节点中实现浏览器的JavaScript获取API。这样,我们可以丢弃大约11行代码(减少25%),并使代码更容易阅读。
运行上述代码的结果与我们前面的示例相同。
转移变量
在本例中,我们的查询有一个需要传递的更改
量($id)。为了传递这个变量,我们需要将变量值添加到请求正文中包含的数据里。这应该是一个 JSON 格式的列表,其中查询所需的每个变量在 JSON 中都有一个对应的值。在本例中,我传递的 ID 值为 1,它返回的是 Scooby Doo,这不是什么巧合:
现在我们知道 Scooby Doo 在哪里了。
使用客户端 JavaScript 发送查询
通过客户端 JavaScript 调用 GraphQL 查询的操作与上面的 fetch 示例几乎是一样的,只有一些很小的区别。首先,我显然不需要导入一个库来支持 fetch。其次,更重要的是我无法访问环境变量。需要强调的是,如果你的 API 需要传递某种 API 密钥或凭据,那么你不会希望在客户端执行这一操作,因为你的凭据将被公开。更好的解决方案是调用一个可访问这些凭据的无服务器函数,然后为你调用 API 并返回结果。如果你的无服务器函数是用 JavaScript 编写的,则前面示例中的 Node 代码就会起作用。不过在 API 完全开放的情况下,我们先来看一下它是如何完成的(请注意,我的示例确实有一个 API 密钥,但请按照我说的那样做,不要像在演示中那样对付一下……)。
以下示例调用了我的 Scooby API 来获取一个 monster 列表和它们所出现的剧集列表(抱歉,Scooby 粉丝们,我现在只统计了第 1 季中的少数 monster)。然后它会获取结果并将其显示在浏览器中。尽管这对 GraphQL 调用来说并不重要,但我使用 js-beautify 正确格式化了要显示的 JSON 结果,然后使用 Prism 给它上了色。
运行以上代码的结果是 JSON 响应,其中包含浏览器中显示的角色和剧集数据。
显然,一般来说你不会想要简单地向用户显示查询结果,因此让我们看一下如何使用返回的数据。
使用 GraphQL 查询响应
GraphQL 的一大优点是,它的响应只是纯 JSON,因此数据使用起来很容易。这里更好的是响应对应了查询,这意味着你无需花费大量时间来分析关于响应的文档。因此我们可以快速采用上面的示例并利用返回的数据,而不是简单地把它摆出来。
下面的代码会获取 JSON 响应,然后将其转换为 HTML(使用模板字面量),以将各项附加到一个 HTML 列表上。
运行这个简单示例的输出是一个角色及其出现剧集的无序列表。
接下来可以做什么
这里的目标不是让大家不要使用 GraphQL 客户端库来执行 GraphQL 查询。那些库提供的能力远远超过了我在这里讨论的简单功能。此外,许多工具具备很容易和前端框架(例如 React、Vue、Angular)集成的能力。但是,对于研究 GraphQL 的人们来说(尤其是将其与 REST 对比时),很重要的一点是使用 GraphQL 显然不需要任何外部依赖项。如果你有兴趣探索一些 JavaScript 库,请参考下面的这些流行选项:
Apollo Client
https://github.com/apollographql/apollo-client
urql
https://formidable.com/open-source/urql/
Relay
https://relay.dev/
GraphQL Request
https://github.com/prisma-labs/graphql-request
作者介绍
Brian Rinaldi 是 StepZen 的一位开发倡导者。Brian 在 Progress Software 和 Adobe 等公司已有 10 多年的经验,一直致力于开发者社区和开发者关系工作。Brian 加入软件开发行业已超过 20 年,主要研究 Web 前端和后端技术。