原文: 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的緣由和方法。