原文: https://medium.com/free-code-camp/give-it-a-....
译者:前端技术小哥
如今愈来愈多的公司开始用GraphQL来创建API。咱们获取数据的方式发生了革命性的变化。
GraphQL的起源以及咱们为何要使用这种方法
GraphQL来自于facebook。facebook内部正在寻找一种让他们的新闻推送在移动平台上加载的更稳定的方法。 前端
使用传统REST API结构,新闻推送对多个API端点进行了多重调用,以便得到所需的全部数据。可是这一路走来,API调用也会取到新闻推送那部分不须要的多余数据。不只如此,在收到数据以后,前端工程师还必须经过数据解析找到他们想要的片断。
facebook工程师想知道,“若是咱们能够编写指令语言,那么咱们能够在单个API请求中找到须要的全部信息?” git
GraphSQL是工程师们努力的研究结果。首先它将数据库中对象之间的关系映射到咱们建立的一个图表中。而后他们设计了一个指令语言来找到这些关系的映射。所以,它被命名为“GraphSQL”。
经过添加查询语言,GraphSQL API如今能够接受单个端点的全部接收请求。而后,他们取回并返回所请求的数据,而且只返回到所请求的数据。这样将再也不重复获取用户不使用的信息。 数据库
是一份规范而不是实现方法
最重要的是,Facebook决定开放源代码GraphQL做为一份规范。
这意味着它能够经过任何编程语言实现。只要实现以规定的方式分析指令得出它的框架,它就能很好地运行任何其余GraphQL应用程序。
事实上,如今每种主流编程语言中都有几十种实现GraphQL的方法。
在本文中,咱们将使用JavaScript编写的GraphQL来实现,这是在任何语言中都适用的相同基本原则。您能够查看GraphQL实现的完整列表,以找到您最喜欢的语言。express
开发一个功能良好的GraphQL API须要两个部分:服务器和客户端。服务器处理传入的指令,解析这些指令,使用规范来获取数据,并经过JSON进行返回。
客户端使您的应用程序可以与服务器通讯。虽然您只需向GraphQL端点发送简单的POST请求,可是若是使用GraphQL客户端来帮助发送指令,则能够得到更好的使用效果。
构建GraphQL API可能比构建REST API更加的集中。然而,在速度和实际应用上的优势能够弥补它在复杂或高强度的应用程序运行的不足。npm
咱们API的目标是发送一个GraphQL指令并收到一个响应。咱们一块儿来看看GraphQL大概是什么样的。
记住,GraphQL是它本身的语言。它并非一种很难学习的语言,并且在很大程度上编写指令是很直接的。让咱们想象一下,咱们有一个包含了飞机和乘客信息的数据库。在GraphQL中,咱们能够这样定义飞机:编程
{ flight(id: "1234") { origin destination } }
这是GraphQL所发出的:“给我飞机1234的始发地和目的地。”咱们会收到这样的回应:json
{ "data": { "flight": { "origin": "DFW", "destination": "MKE" } } }
提示:
咱们收到正好都是咱们指令所要求的内容,很少也很多。
咱们还收到了与咱们发送的原始指令彻底相同的格式响应。这些是GraphQL API的标记。这是GraphQL如此快速和强大的缘由。
不过,这并非咱们所能作的事情。咱们想要获得这架飞机上的乘客信息,该怎么作:api
{ flight(id: "1234") { origin destination passengers { name } } }
如今,GraphQL将向下扫描该航班与乘客之间的关系图。咱们会获得一份乘客名单反馈:
如今咱们能够用一个API调用当即查看此航班上的全部乘客。
为何小小小黄正在飞往国内,因为GraphSQL将数据分析为图形,咱们也能够在其余方向进行扫描。前端框架
{ "data": { "flight": { "origin": "DFW", "destination": "MKE", "passengers": [ { "name": "小明" }, { "name": "小黄" }, { "name": "小小" } ] } } }
如今咱们能够看到飞机Luke记录了什么:服务器
{ "data": { "person": { "passport_number": 78120935, "flights": [ { "id": "1234", "date": "2019-05-24", "origin": "DFW", "destination": "MKE" }, { "id": "2621", "date": "2019-07-05", "origin": "MKE", "destination": "DFW" } ] } } }
哇,他要在密尔沃基呆一个多月了!我想知道他在那里干什么?
列一项清单
最终,GraphQL的大多数使用将涉及到与数据库的对话。在本教程中,咱们将不讨论向Express添加数据库和容许GraphQL查询和更新该数据库。这是一个彻底不一样的教程。
首先,须要为API奠基基础。您将须要安装的Nodejs和NPM随本教程今后处退出。
构建一个Barbones Express服务器。启动NPM:
$ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. package name: (graphql-medium) version: (1.0.0) description: entry point: (index.js) test command: git repository: keywords: author: license: (ISC) About to write to /home/bennett/Repos/graphql-medium/package.json: { "name": "graphql-medium", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } Is this OK? (yes)
只需点击Enter就能够跳过初始化过程。也能够回头编辑Package.json。接下来,让咱们安装Express、GraphQL和Express-GraphQL库:
$ npm install express express-graphql graphql npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN graphql-medium@1.0.0 No description npm WARN graphql-medium@1.0.0 No repository field. + express-graphql@0.8.0 + graphql@14.3.1 + express@4.17.0 added 53 packages from 38 contributors and audited 151 packages in 6.169s found 0 vulnerabilities
如今,咱们将建立一个名为index.js的新文件,并在那里建立一个新的barebones Express
服务器:
// index.js const express = require('express'); const app = express(); app.get('/', function(req, res) { res.send('Express is working!') }); app.listen(4000, function() { console.log('Listening on port 4000') });
尝试运行节点index.js。您应该会看到一条“Listening on port 4000”的消息,若是您访问http://localhost:4000/
,您将看到“Express正在工做”
添加GraphQL&DefineSchema
咱们已经安装了GraphQLNPM
包。如今能够运行这个程序了。
首先,咱们须要导入必要的模块:
const graphqlHTTP = require('express-graphql'); const { buildSchema } = require('graphql');
让咱们开始定义GraphQL API的结构。输入的指令应该是什么样的?如今,让咱们定义一个HelloWorld模式,以获取工做的事物:
let schema = buildSchema(` type Query { hello: String } `);
这个简单的模式让GraphQL知道,当有人发送查询“Hello”时,咱们将返回一个字符串。注意里面的那些小后背 ` 。这代表咱们使用的是JavaScript模板文字。基本上,咱们使用这些回退来告诉JavaScript,咱们将要用另外一种语言编写GraphQL指令的语言。
所以,当有人为Hello提交指令时,咱们知道咱们将返回一个字符串。这是在咱们的模式中定义的。如今,咱们须要确切地告诉GraphQL它应该返回什么字符串。根据输入的指令肯定要返回的数据是GraphQL中“解析器”的工做。在本例中,分析方法很简单。咱们将返回字符串“Hello world”。
return 'Hello world!';
可是,咱们须要将该返回语句放在一个能够屡次调用的函数中,不管什么时候有人在hello中编写指令:
function() { return 'Hello world!'; }
如今,hello可能不是咱们实现的惟一指令的类型。将来,咱们可能还包括其余功能的“端点”。所以,咱们应该确保咱们刚刚建立的这个函数映射到hello与咱们API的全部其余部分一块儿,保存在一个对象中。
let root = { hello: function() { return 'Hello world!'; }, }
这是一个调用对象的公约,它能够保留全部解析器的原始数据,不管您须要什么,均可以经过它获得。
精明的读者会注意到,咱们在步骤2中导入了GraphqlHTTP,但咱们尚未使用它。如今是时候了。咱们如今已经为GraphSQLServer提供了一切。咱们只须要经过URL端点提供它。在Express中,咱们将建立一个新的路由来服务GraphSQLAPI
app.use('/graphql', graphqlHTTP({ schema: schema, rootValue: root, graphiql: true, }));
模式和原始数据指向步骤2和3中定义的变量。GraphSQL是一个有用的可视化工具,它与GraphSQL一块儿安装。正如咱们将在第二个中看到的,它很容易得出您的API是如何工做的。这是咱们的GraphSQLServer源代码的最终状态。
运行程序&输入一个指令
准备测试该程序!
用npm index.js
启动应用程序
转到http://localhost:4000/GraphSQL
您应该看到GraphSQL界面:
咱们如今可使用这个接口来确保咱们的API正在工做!
让咱们写一个指令。这个很简单的。咱们老是在大括号中写咱们的GraphSQL指令。而后,咱们指定要提取的任何属性所对应的模式对象。
在这种状况下,目前咱们API中只有一个东西要提取:
{ hello }
若是你点击了提交按钮,你将会看到:
{ "data": { "hello": "Hello world!" } }
它正在工做!
添加更多的端点
向API添加端点就像在模式中定义新字段同样简单,而后将解析器函数添加到原始数据中。
您也可让指令逐渐变得复杂。下一步,我推荐这个来自官方文档的引导building a dice rolling API。
GraphQL很是好用,它在应用中迅速成长。在将来的几年里,它有可能成为一种无处不在的API技术。但愿本文为您很好地介绍了能够在项目中使用GraphQL的缘由和方法。