實踐篇:GraphQL瞭解一下:實踐篇
進階篇:GraphQL進階篇: 揮手Redux不是夢前端
GraphQL由Facebook發起,其手機客戶端自2012年起,就全面採用了GraphQL查詢語言, 2015年, Facebook全面開源了第一份GraphQL規範。到目前爲止,在Twitter,Github,Pinterest,Shopify等大型網站也獲得了普遍的實踐。語言也從最初的js,擴展到java ,python,Go。且Apollo-client也逐漸作全了graphql生態。
GraphQL是一種用於 API 的查詢語言(規範),是一種協議而非存儲。GraphQL對你的API中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘;
若是想在讀下面的知識以前,對GraphQL先有一個粗狂的認識,能夠登陸GitHub GraphQL API 站點,體會一下其使用,可點擊右側的Doc文檔查看接口定義。 java
上面是一張咱們經常使用的Restful接口交互和引入GraphQL接口中間層的接口交互對比圖,在此以前,咱們先了解一下當前咱們所使用的Restful接口的痛點:python
相信上面的三點,在前端淌過水的你,必定是會有體會的。一個接口,同時用於h5頁面和web頁面的渲染源數據,但可能H5頁面只須要這些數據源的1/10,冗餘數據的返回浪費了流量,消耗了時間;因爲如今後端更推崇microservice,提供聚合服務的API被認爲沒有技術含量,因此咱們有時渲染一個關係複雜的頁面,須要請求5,6次,才能完整的渲染出一個頁面,這期間咱們還得去容錯,避免因其中某一個請求的失敗致使頁面沒法渲染的問題;API文檔更新不及時,相信這是最多見的吐槽,好好的靜態頁面寫完,並本身照着API文檔作完mock,等聯調時,接口返回的字段徹底不按API定義來,奔潰。
上圖摘自GraphQL官網,其用簡單的三句話:描述你的數據(服務端),請求你所要的數據(客戶端),獲得可預測的結果。其隱藏的意思就是:react
聽起來是否是特別爽,那實現起來呢?git
其實GraphQL所須要學習的語法不多,大部分語法與咱們平時的語法一致,能夠經過官網詳細瞭解。首先,GraphQL是一門強類型語言,因此和咱們在數據庫定義一張表同樣,咱們須要定義每個屬性的類型.以下圖所示:github
enum Episode { NEWHOPE EMPIRE JEDI } type Person{ id: ID! name: String! friends: [Person] appearsIn: [Episode]! }
上面是一個簡單的類型定義,先是定義了一個枚舉,而後咱們定義了一個類型,類型中有四個屬性:id、 name、 friends、 appearsIn,其中id和name是標量類型,而friends是一個Person類型,這是一個嵌套類型,仔細想一想應該沒什麼毛病,畢竟你的朋友和你同樣,都是人;而appearsIn是一個枚舉類型,看起來仍是很熟悉的;
瞭解完類型,再瞭解一下Arguments和resolver,二者都是偏服務端一些,可是瞭解一下,對graphql的使用原理有進一步的認識;
對於一個Restful API來說,除了知道接口URL,咱們還須要知道接口的傳參定義,對於GraphQL其實也同樣,雖然URL只有一個,不一樣的接口經過type來區別,但傳參同Restful API同樣,體現了客戶端與服務端的交互。好比下面,查詢的目標是id = 2的用戶,獲取他的用戶名:web
Query{ user(id: 2) { id userName } }
而在服務端定義一個接口時,咱們也須要去定義入參,主要從兩個方面,一是類型,二是其是否必填,好比下面這樣:
接口定義 數據庫
user: { type: UserType, args: { id: { type: GraphQLID } }, resolve: (root, args, context, info) => { const { id } = args; return getUser(id); } }
查詢定義 編程
上面的代碼只是定義了一個輸入屬性id,並未定義其是不是必填,因此當查詢時,若是沒有配置查詢id,查詢不會報錯,只會獲取一個爲null的空值結果。可是講道理的話,咱們但願這是一個必填項,因此咱們須要修改服務端的代碼,將id: { type: GraphQLID } 更換爲id: {type: new GraphQLNonNull(GraphQLID)},這句代碼的含義就表示id是一個類型爲ID的必填項,再次執行咱們的查詢能夠獲得下面的錯誤提示,提示id是一個必填的ID類型,同時右側也沒有獲取到爲空的查詢結果;後端
在講上面Arguments時候,能夠零星的看到type中有一個resolve方法,其接收root, args, context, info四個參數。其中root表明這個type上父節點的resolve值(由於GraphQL支持嵌套查詢),args就是上面講的,context表在Resolver解析鏈中不斷傳遞的中間變量,和react的上下文類似,而info這個概念,是當前Query的AST對象,比較抽象,可是能夠經過查看info,獲取這個QUERY的編譯對象。這個方法也是後端服務編寫的重點部分,經常咱們能夠在這裏與已有的Restful API關聯起來。
Schema能夠說是GraphQL最具核心的部分,其描述了整個接口向外暴露的形式;像Restful API,咱們會定義一個查詢全部人的接口url定義爲:/api/v1/user/getUsers,而查詢人具體信息的接口url爲:/api/v1/user/getUserById,而新增一我的員的接口url定義爲:/api/v1/user/createUser,前端人員調用起來很直觀。可是graphql是徹底不同的使用方式,其向前端暴露的url就一個像/api/graphql之類的,那這麼多接口怎麼區分呢?
奧妙就是上面這張圖,一個graphql接口都有一個Schema定義,其定義三種操做方式:query(查詢),mutation(變動)和subscription(監聽)。再往下延伸,一個查詢中包含多個field,也就是多種不一樣的查詢,好比query user查詢人,query message查詢消息,query weather查詢天氣,經過這些就實現了Restful API使用多個url來達到不一樣操做的效果。看下面一張圖(使用最原生的graphql語言編寫,有助於理解):
這是一篇本身學習GraphQL期間,概括總結到的信息,本身感受是同如今的開發方式相比,須要在前端與Restful API之間增長一層GraphQL中間層,這確實增長了工做量,但看上面提到的語法,其編程仍是很是直觀易懂的,在業務不是那麼繁重的時候,仍是值得推廣的。在下一篇將會講到:實現一個GraphQL Server與在React應用中引入GraphQL。