天天看點

一文快速入門 Graphql

一張腦圖總結全文:

一文快速入門 Graphql

GraphQL 是由 Facebook 開發并開源的。提到 GraphQL ,大家自然而然會提起 RESTful api。下面對比一下 RESTful api 和 GraphQL 的優缺點。

聲明式的接口擷取 RESTful api 傳回的字段備援, 當多個終端共用接口時,尤其明顯。GraphQL 可精準的傳回所需的資料結果,減少資料傳輸大小。

嵌套複雜資料僅需一次調用 RESTful 對于嵌套的複雜資料需要多次調用,而 GraphQL 隻需要一次。

愉快地前後端聯調效率 REST 每次新加字段,需頻繁溝通,且需借助 swagger 生成接口文檔, GraphQL 自動生成标準文檔。

如果上面的優點看不懂,沒關系,我們來舉一個栗子,加速了解:

服務端 getUser 接口傳回了 id, name 資訊, 但是另外一個場景,需要額外多傳回幾個字段, 比如 email, adress 等。此時服務端要怎麼做?有以下三種做法:

新開一個接口, 傳回所需要的所有字段

請求增加一個 type ,用于區分場景,服務端根據不同 type 傳回不同的字段

不管三七二十一, 在原有接口上增加多的字段。

如果隻是 1 個,2 個場景還好,但如果後期有 n 個場景,需要傳回非常多的字段,這不僅會浪費帶寬,用戶端資料解析也會影響響應時間,進而影響使用者體驗。那讓背景新增一個接口可以嗎?當然可以,可是這樣背景需要額外維護這種“業務邏輯”。

查詢( query )

更新( mutation )

訂閱( subscription )

我一直提倡,剛開始學習一門新的技術,别看太多文檔,先用它的 api, 快速做一個 demo ,跑起來之後。再開始系統學習,這樣效率是最高的。是以,下面我們會實戰來做一個 GraphQL .

跟着官方文檔[1]簡單快速建立一個栗子。

打開 index.js ,将以下代碼複制粘貼進去。

我們在上面的 index.js 檔案後面,繼續複制粘貼

在指令行中運作 index.js

好了, 就是這麼簡單,一個 graphql 就寫好了。實際中的項目可能使用 egg 或者 koa 或者 express。本質的思想是一樣的, 都是先定義 GraphQL schema ,再定義 resolver ,resolver 這裡從不同地方取數,再之後就是傳遞 schema 和 resolver,建立執行個體。

上面的代碼運作起來了,要去哪裡調用?如果是用 RESTful api ,我們會用 postman 來測試接口是否可以跑通。同樣的,GraphQL 可以用 GraphiQL 來測試。

按需取用:

一文快速入門 Graphql

除了可以用來測試接口之後,它還是一個文檔工具,使用 GraphiQL 可以很容易地讓人感受到“代碼即文檔”的快樂。

一文快速入門 Graphql

你可以在這裡檢視測試的曆史

一文快速入門 Graphql

從上面的例子看出,要先定義 Schemas, 那我們就來學習下 Schemas。如果你使用過 Typescript ,會發現它的類型跟 Typescript 特别的類似。

Int, Float, String, Boolean, ID(唯一辨別符)

enum, Date, interface

!(不可為 null) 可通過 Union types 或 implements 擴充上面的類型。

查詢(query)和變更類型(mutation)

檢視官方文檔[2]

我們可以簡單地了解成,針對我們暴露的接口,調用相應的方法去取數傳回。resolver 的解析規則是, 從外到内依次處理查詢塊,為每一個查詢塊執行對應的 resolver 函數,并傳遞外層調用傳回的結果作為第一個參數,也就是下面代碼中的 obj 。

resolver 函數它接收 4 個參數

同樣的,我們直接來看一個例子:在 index.js 中修改對應的 Schemas 和 Resolver

由于這個 resolver 函數第一個參數是傳遞外層調用的傳回結果,這裡我們沒有嵌套 resolver ,是以我們直接用第二個參數 id 擷取前端傳入的參數。

更多内容檢視 resolver 文檔[3]

然後我們在 http://127.0.0.1:4000/graphql 或者在用戶端 GraphiQL 中測試

一文快速入門 Graphql

已經成功找到對應 id 的資料了,但是這裡的 id 是寫死的,我們說 graphql 最大的好處是聲明式擷取,那如何把 id 變成一個變量,讓外部傳入?

一文快速入門 Graphql

給傳回的值設定别名

一文快速入門 Graphql

好了,接口正常傳回。

更多查詢變更可看官方文檔[4]

在實際項目中,我們會将資料庫 ,dataloaders 注入到 context 中,友善所有 resolver 調用。

Dataloader 是 facebook 搞的一個 js 庫,可以大幅降低資料庫的通路頻次,進而降低系統負載,經常在 Graphql 場景中使用。通過使用 dataloader,資料庫的通路頻次可以指數級别下降。

dataloader 是如何工作的呢,可以看下圖:

一文快速入門 Graphql

對于 User 表的多次通路,通過 dataloader 去取,會自動合并為一個請求。dataloader 之是以可以實作這樣的能力,是因為他把每一次資料請求,都推遲到 node 的 Next Tick 後集中批處理運作,這樣就可以對請求進行加工合并。