摘要:我們知道是一種從服務器公開數據的流行方式。描述所有的可能類型系統基于類型和字段的方式進行組織,而非入口端點。因此,需要對后端進行調整,以滿足新的數據需求,這會降低生產力并顯著降低將用戶反饋集成到產品中的能力。
在前幾天的《StateOfJS: 2018年JavaScript生態圈趨勢報告》一文中,我們看到了2018年在數據層GraphQL的發展勢頭猛烈,并且大部分用戶用過都說好,但如上圖數據顯示,目前國內的使用人數還很少,大部分人連聽都沒聽過,今天小肆就為大家介紹一下,何為GraphQL。一. GraphQL為何會出現?
當提起API設計的時候,大家通常會想到SOAP,RESTful等設計方式,從2000年RESTful的理論被提出的時候,在業界引起了很大反響,因為這種設計理念更易于用戶的使用,所以便很快的被大家所接受。我們知道REST是一種從服務器公開數據的流行方式。
當REST的概念被提及出來時,客戶端應用程序對數據的需求相對簡單,而開發的速度并沒有達到今天的水平。
因此REST對于許多應用程序來說是非常適合的。然而在業務越發復雜,客戶對系統的擴展性有了更高的要求時,API環境發生了巨大的變化。特別是從下面三個方面在挑戰api設計的方式:
1. 移動端用戶的爆發式增長需要更高效的數據加載Facebook開發GraphQL的最初原因是移動用戶的增加、低功耗設備和松散的網絡。GraphQL最小化了需要網絡傳輸的數據量,從而極大地改善了在這些條件下運行的應用程序。
2. 各種不同的前端框架和平臺前端框架和平臺運行客戶端應用程序的異構環境使得我們在構建和維護一個符合所有需求的API變得困難,使用GraphQL每個客戶機都可以精確地訪問它需要的數據。
3. 在不同前端框架,不同平臺下想要加快產品快速開發變的越來越難持續部署已經成為許多公司的標準,快速的迭代和頻繁的產品更新是必不可少的。對于REST api,服務器公開數據的方式常常需要修改,以滿足客戶端的特定需求和設計更改。這阻礙了快速開發實踐和產品迭代。
二. GraphQL官方定義:一種用于 API 的查詢語言
GraphQL 既是一種用于 API 的查詢語言也是一個滿足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易于理解的完整描述,使得客戶端能夠準確地獲得它需要的數據,而且沒有任何冗余,也讓 API 更容易地隨著時間推移而演進,還能用于構建強大的開發者工具。
向你的 API 發出一個 GraphQL 請求就能準確獲得你想要的數據,不多不少。 GraphQL 查詢總是返回可預測的結果。使用 GraphQL 的應用可以工作得又快又穩,因為控制數據的是應用,而不是服務器。
獲取多個資源:只用一個請求GraphQL 查詢不僅能夠獲得資源的屬性,還能沿著資源間引用進一步查詢。典型的 REST API 請求多個資源時得載入多個 URL,而 GraphQL 可以通過一次請求就獲取你應用所需的所有數據。這樣一來,即使是比較慢的移動網絡連接下,使用 GraphQL 的應用也能表現得足夠迅速。
描述所有的可能:類型系統GraphQL API 基于類型和字段的方式進行組織,而非入口端點。你可以通過一個單一入口端點得到你所有的數據能力。GraphQL 使用類型來保證應用只請求可能的數據,還提供了清晰的輔助性錯誤信息。應用可以使用類型,而避免編寫手動解析代碼。
三. GraphQL和RESTful的區別前面提到GraphQL可以理解為基于RESTful的一種封裝,目的在于構建使Client更加易用的服務,可以說GraphQL是更好的RESTful設計。
在過去的十多年中,REST已經成為設計web api的標準(雖然只是一個模糊的標準)。它提供了一些很棒的想法,比如無狀態服務器和結構化的資源訪問。
然而REST api表現得過于僵化,無法跟上訪問它們的客戶的快速變化的需求。 GraphQL的開發是為了應付更多的靈活性和效率,它解決了與REST api交互時開發人員所經歷的許多缺點和低效之處。
為了說明在從API獲取數據時REST和GraphQL之間的主要區別,讓我們考慮一個簡單的示例場景:在blog應用程序中,應用程序需要顯示特定用戶的文章的標題。同一屏幕還顯示該用戶最后3個關注者的名稱。
REST和GraphQL如何解決這種情況?
使用REST API來現實時,我們通常可以通過訪問多次請求來收集數據。
比如在這個示例中,我們可以通過下面的三步來實現:
通過 /user/
通過/user/
請求/user/
調用關系如下圖所示:
如果用GraphQL的話,我們只需要一次請求就可以完成上述的需求
在GraphQL的世界里我們不用多取數據,也不用擔心數據取少了,我們只需要按需獲取即可。
REST最常見的問題之一是API的返回數據過多或者過少,這是因為客戶端下載數據的唯一方法是通過訪問返回固定數據結構的endpoint,這就會導致我們設計API非常困難,因為它既要能夠為客戶提供精確的數據需求,又需要滿足不同調用者的需求,這本身就是相互矛盾的。GraphQL的發明者Lee Byron提出了一個很重要的概念: “用圖形來思考,而不是endpoint”
通過上述直觀展示我們可以得出一下幾點:
1. 獲取了許多多余的數據通常情況下我們在調用一個通用API接口時,客戶端獲取的信息比應用程序中實際需要的要多。例如UI需要顯示一個用戶列表,而實際上只需要使用他們的名字。在REST API中通常會調用 /user 這個endpoint,并接收一個帶有用戶數據的JSON數組。但是這個響應可能包含更多關于返回的用戶的信息,例如他們的生日或地址,而這些信息對客戶來說是無用的,因為它只需要顯示用戶的名字。
2. 獲取的數據少于Client所需要的數據一般來說數據獲取不足意味著某個特定的endpoint沒有提供客戶端需要的足夠信息,客戶端將需要額外的請求來獲取它所需要的一切。這可能會升級到客戶端需要首先獲取列表信息,然后需要對單條數據添加一個額外的請求以獲取其他所需的數據。
3. 前端的快速產品迭代對API有很大的挑戰REST api的一個常見模式是根據您在應用程序內部的展現邏輯來構造endpoint,這很方便,因為它允許客戶端通過訪問相應的endpoint獲取特定視圖的所有所需信息。
這種方法的主要缺點是它不允許前端的快速迭代。對于UI所做的每一個更改,現在都存在比以前更多(或更少)的數據的高風險。
因此,需要對后端進行調整,以滿足新的數據需求,這會降低生產力并顯著降低將用戶反饋集成到產品中的能力。 使用GraphQL這個問題就解決了。
由于GraphQL的靈活性,無需在服務器上額外工作就可以在客戶端上進行更改。由于客戶端可以指定準確的數據需求,所以當前端的設計和數據需求發生變化時,并不需要后端API做出任何的修改就可以滿足展現層的變化。
4. Schema和類型系統的好處GraphQL使用強大的Type System來定義API的功能。所有在API中公開的類型都是使用GraphQL schema Definition Language (SDL)在模式中編寫的。
該模式充當客戶端和服務器之間的契約,以定義客戶機如何訪問數據。 一旦定義了模式,在前端和后端工作的團隊就可以在沒有進一步通信的情況下完成工作,因為他們都知道通過網絡發送的數據的確切結構。
前端團隊可以通過mock所需的數據結構來輕松測試他們的應用程序。一旦后端API實現完成,就可以對客戶端應用程序進行切換來調用實際的API獲取數據,這也可以使得我們實現更好的客戶端和服務端的分離。
四. GraphQL語法 基礎語法其實GraphQL所需要學習的語法很少,大部分語法與我們平時的語法一致,可以通過官網詳細了解。
首先,GraphQL是一門強類型語言,所以和我們在數據庫定義一張表一樣,我們需要定義每一個屬性的類型.如下圖所示:
下面是一個簡單的類型定義,先是定義了一個枚舉,然后我們定義了一個類型,類型中有四個屬性:id、 name、 friends、 appearsIn,其中id和name是標量類型,而friends是一個Person類型,這是一個嵌套類型,仔細想想應該沒什么毛病,畢竟你的朋友和你一樣,都是人,而appearsIn是一個枚舉類型,看起來還是很熟悉的。
enum Episode { NEWHOPE EMPIRE JEDI } type Person{ id: ID! name: String! friends: [Person] appearsIn: [Episode]! }
了解完類型,再了解一下Arguments和resolver,兩者都是偏服務端一些,但是了解一下,對graphql的使用原理有進一步的認識。
對于一個Restful API來講,除了知道接口URL,我們還需要知道接口的傳參定義,對于GraphQL其實也一樣,雖然URL只有一個,不同的接口通過type來區別,但傳參同Restful API一樣,體現了客戶端與服務端的交互。
比如下面,查詢的目標是id = 2的用戶,獲取他的用戶名:
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的出現可以使我們后端API具有更大的靈活性以及擴展性,滿足了不同client對數據的需要,大大豐富了API的數據提供的能力。
部分內容來源:https://segmentfault.com/a/11...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100979.html
摘要:我們知道是一種從服務器公開數據的流行方式。描述所有的可能類型系統基于類型和字段的方式進行組織,而非入口端點。因此,需要對后端進行調整,以滿足新的數據需求,這會降低生產力并顯著降低將用戶反饋集成到產品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:我們知道是一種從服務器公開數據的流行方式。描述所有的可能類型系統基于類型和字段的方式進行組織,而非入口端點。因此,需要對后端進行調整,以滿足新的數據需求,這會降低生產力并顯著降低將用戶反饋集成到產品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:我們知道是一種從服務器公開數據的流行方式。描述所有的可能類型系統基于類型和字段的方式進行組織,而非入口端點。因此,需要對后端進行調整,以滿足新的數據需求,這會降低生產力并顯著降低將用戶反饋集成到產品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:允許創建零配置的服務器。這是一種人類可讀的模式語法,稱為規范與描述語言。類型是表示外觀的自定義對象。為此,創建一個名為的新查詢。這意味著無論何時在服務器中發生事件,并且每當調用該事件時,服務器都會將相應的數據發送到客戶端。 showImg(https://segmentfault.com/img/bVbm0c1?w=2560&h=1024); 想閱讀更多優質文章請猛戳GitHub博客,...
摘要:騰訊空間超分辨率技術為用戶節省流量,處理效果和速度超谷歌技術在的標準下,處理速度在提升了,處理效果也有明顯提升。此外,也是業界首次實現移動端使用深度神經網絡進行超分辨率,并保證圖片能夠實時進行處理。值得一提的是的對應指標也在名單里。 團隊分享 魔幻語言 JavaScript 系列之 call、bind 以及上下文 從一行代碼來看看 JavaScript 是一門多么魔幻的語言,順便談談 ...
閱讀 1883·2021-11-22 09:34
閱讀 3010·2021-09-28 09:35
閱讀 13375·2021-09-09 11:34
閱讀 3594·2019-08-29 16:25
閱讀 2820·2019-08-29 15:23
閱讀 2035·2019-08-28 17:55
閱讀 2424·2019-08-26 17:04
閱讀 3044·2019-08-26 12:21