摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對(duì)后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會(huì)降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。
在前幾天的《StateOfJS: 2018年JavaScript生態(tài)圈趨勢(shì)報(bào)告》一文中,我們看到了2018年在數(shù)據(jù)層GraphQL的發(fā)展勢(shì)頭猛烈,并且大部分用戶用過都說好,但如上圖數(shù)據(jù)顯示,目前國內(nèi)的使用人數(shù)還很少,大部分人連聽都沒聽過,今天小肆就為大家介紹一下,何為GraphQL。一. GraphQL為何會(huì)出現(xiàn)?
當(dāng)提起API設(shè)計(jì)的時(shí)候,大家通常會(huì)想到SOAP,RESTful等設(shè)計(jì)方式,從2000年RESTful的理論被提出的時(shí)候,在業(yè)界引起了很大反響,因?yàn)檫@種設(shè)計(jì)理念更易于用戶的使用,所以便很快的被大家所接受。我們知道REST是一種從服務(wù)器公開數(shù)據(jù)的流行方式。
當(dāng)REST的概念被提及出來時(shí),客戶端應(yīng)用程序?qū)?shù)據(jù)的需求相對(duì)簡單,而開發(fā)的速度并沒有達(dá)到今天的水平。
因此REST對(duì)于許多應(yīng)用程序來說是非常適合的。然而在業(yè)務(wù)越發(fā)復(fù)雜,客戶對(duì)系統(tǒng)的擴(kuò)展性有了更高的要求時(shí),API環(huán)境發(fā)生了巨大的變化。特別是從下面三個(gè)方面在挑戰(zhàn)api設(shè)計(jì)的方式:
1. 移動(dòng)端用戶的爆發(fā)式增長需要更高效的數(shù)據(jù)加載Facebook開發(fā)GraphQL的最初原因是移動(dòng)用戶的增加、低功耗設(shè)備和松散的網(wǎng)絡(luò)。GraphQL最小化了需要網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量,從而極大地改善了在這些條件下運(yùn)行的應(yīng)用程序。
2. 各種不同的前端框架和平臺(tái)前端框架和平臺(tái)運(yùn)行客戶端應(yīng)用程序的異構(gòu)環(huán)境使得我們?cè)跇?gòu)建和維護(hù)一個(gè)符合所有需求的API變得困難,使用GraphQL每個(gè)客戶機(jī)都可以精確地訪問它需要的數(shù)據(jù)。
3. 在不同前端框架,不同平臺(tái)下想要加快產(chǎn)品快速開發(fā)變的越來越難持續(xù)部署已經(jīng)成為許多公司的標(biāo)準(zhǔn),快速的迭代和頻繁的產(chǎn)品更新是必不可少的。對(duì)于REST api,服務(wù)器公開數(shù)據(jù)的方式常常需要修改,以滿足客戶端的特定需求和設(shè)計(jì)更改。這阻礙了快速開發(fā)實(shí)踐和產(chǎn)品迭代。
二. GraphQL官方定義:一種用于 API 的查詢語言
GraphQL 既是一種用于 API 的查詢語言也是一個(gè)滿足你數(shù)據(jù)查詢的運(yùn)行時(shí)。 GraphQL 對(duì)你的 API 中的數(shù)據(jù)提供了一套易于理解的完整描述,使得客戶端能夠準(zhǔn)確地獲得它需要的數(shù)據(jù),而且沒有任何冗余,也讓 API 更容易地隨著時(shí)間推移而演進(jìn),還能用于構(gòu)建強(qiáng)大的開發(fā)者工具。
向你的 API 發(fā)出一個(gè) GraphQL 請(qǐng)求就能準(zhǔn)確獲得你想要的數(shù)據(jù),不多不少。 GraphQL 查詢總是返回可預(yù)測(cè)的結(jié)果。使用 GraphQL 的應(yīng)用可以工作得又快又穩(wěn),因?yàn)榭刂茢?shù)據(jù)的是應(yīng)用,而不是服務(wù)器。
獲取多個(gè)資源:只用一個(gè)請(qǐng)求GraphQL 查詢不僅能夠獲得資源的屬性,還能沿著資源間引用進(jìn)一步查詢。典型的 REST API 請(qǐng)求多個(gè)資源時(shí)得載入多個(gè) URL,而 GraphQL 可以通過一次請(qǐng)求就獲取你應(yīng)用所需的所有數(shù)據(jù)。這樣一來,即使是比較慢的移動(dòng)網(wǎng)絡(luò)連接下,使用 GraphQL 的應(yīng)用也能表現(xiàn)得足夠迅速。
描述所有的可能:類型系統(tǒng)GraphQL API 基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。你可以通過一個(gè)單一入口端點(diǎn)得到你所有的數(shù)據(jù)能力。GraphQL 使用類型來保證應(yīng)用只請(qǐng)求可能的數(shù)據(jù),還提供了清晰的輔助性錯(cuò)誤信息。應(yīng)用可以使用類型,而避免編寫手動(dòng)解析代碼。
三. GraphQL和RESTful的區(qū)別前面提到GraphQL可以理解為基于RESTful的一種封裝,目的在于構(gòu)建使Client更加易用的服務(wù),可以說GraphQL是更好的RESTful設(shè)計(jì)。
在過去的十多年中,REST已經(jīng)成為設(shè)計(jì)web api的標(biāo)準(zhǔn)(雖然只是一個(gè)模糊的標(biāo)準(zhǔn))。它提供了一些很棒的想法,比如無狀態(tài)服務(wù)器和結(jié)構(gòu)化的資源訪問。
然而REST api表現(xiàn)得過于僵化,無法跟上訪問它們的客戶的快速變化的需求。 GraphQL的開發(fā)是為了應(yīng)付更多的靈活性和效率,它解決了與REST api交互時(shí)開發(fā)人員所經(jīng)歷的許多缺點(diǎn)和低效之處。
為了說明在從API獲取數(shù)據(jù)時(shí)REST和GraphQL之間的主要區(qū)別,讓我們考慮一個(gè)簡單的示例場景:在blog應(yīng)用程序中,應(yīng)用程序需要顯示特定用戶的文章的標(biāo)題。同一屏幕還顯示該用戶最后3個(gè)關(guān)注者的名稱。
REST和GraphQL如何解決這種情況?
使用REST API來現(xiàn)實(shí)時(shí),我們通常可以通過訪問多次請(qǐng)求來收集數(shù)據(jù)。
比如在這個(gè)示例中,我們可以通過下面的三步來實(shí)現(xiàn):
通過 /user/
通過/user/
請(qǐng)求/user/
調(diào)用關(guān)系如下圖所示:
如果用GraphQL的話,我們只需要一次請(qǐng)求就可以完成上述的需求
在GraphQL的世界里我們不用多取數(shù)據(jù),也不用擔(dān)心數(shù)據(jù)取少了,我們只需要按需獲取即可。
REST最常見的問題之一是API的返回?cái)?shù)據(jù)過多或者過少,這是因?yàn)榭蛻舳讼螺d數(shù)據(jù)的唯一方法是通過訪問返回固定數(shù)據(jù)結(jié)構(gòu)的endpoint,這就會(huì)導(dǎo)致我們?cè)O(shè)計(jì)API非常困難,因?yàn)樗纫軌驗(yàn)榭蛻籼峁┚_的數(shù)據(jù)需求,又需要滿足不同調(diào)用者的需求,這本身就是相互矛盾的。GraphQL的發(fā)明者Lee Byron提出了一個(gè)很重要的概念: “用圖形來思考,而不是endpoint”
通過上述直觀展示我們可以得出一下幾點(diǎn):
1. 獲取了許多多余的數(shù)據(jù)通常情況下我們?cè)谡{(diào)用一個(gè)通用API接口時(shí),客戶端獲取的信息比應(yīng)用程序中實(shí)際需要的要多。例如UI需要顯示一個(gè)用戶列表,而實(shí)際上只需要使用他們的名字。在REST API中通常會(huì)調(diào)用 /user 這個(gè)endpoint,并接收一個(gè)帶有用戶數(shù)據(jù)的JSON數(shù)組。但是這個(gè)響應(yīng)可能包含更多關(guān)于返回的用戶的信息,例如他們的生日或地址,而這些信息對(duì)客戶來說是無用的,因?yàn)樗恍枰@示用戶的名字。
2. 獲取的數(shù)據(jù)少于Client所需要的數(shù)據(jù)一般來說數(shù)據(jù)獲取不足意味著某個(gè)特定的endpoint沒有提供客戶端需要的足夠信息,客戶端將需要額外的請(qǐng)求來獲取它所需要的一切。這可能會(huì)升級(jí)到客戶端需要首先獲取列表信息,然后需要對(duì)單條數(shù)據(jù)添加一個(gè)額外的請(qǐng)求以獲取其他所需的數(shù)據(jù)。
3. 前端的快速產(chǎn)品迭代對(duì)API有很大的挑戰(zhàn)REST api的一個(gè)常見模式是根據(jù)您在應(yīng)用程序內(nèi)部的展現(xiàn)邏輯來構(gòu)造endpoint,這很方便,因?yàn)樗试S客戶端通過訪問相應(yīng)的endpoint獲取特定視圖的所有所需信息。
這種方法的主要缺點(diǎn)是它不允許前端的快速迭代。對(duì)于UI所做的每一個(gè)更改,現(xiàn)在都存在比以前更多(或更少)的數(shù)據(jù)的高風(fēng)險(xiǎn)。
因此,需要對(duì)后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會(huì)降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 使用GraphQL這個(gè)問題就解決了。
由于GraphQL的靈活性,無需在服務(wù)器上額外工作就可以在客戶端上進(jìn)行更改。由于客戶端可以指定準(zhǔn)確的數(shù)據(jù)需求,所以當(dāng)前端的設(shè)計(jì)和數(shù)據(jù)需求發(fā)生變化時(shí),并不需要后端API做出任何的修改就可以滿足展現(xiàn)層的變化。
4. Schema和類型系統(tǒng)的好處GraphQL使用強(qiáng)大的Type System來定義API的功能。所有在API中公開的類型都是使用GraphQL schema Definition Language (SDL)在模式中編寫的。
該模式充當(dāng)客戶端和服務(wù)器之間的契約,以定義客戶機(jī)如何訪問數(shù)據(jù)。 一旦定義了模式,在前端和后端工作的團(tuán)隊(duì)就可以在沒有進(jìn)一步通信的情況下完成工作,因?yàn)樗麄兌贾劳ㄟ^網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)的確切結(jié)構(gòu)。
前端團(tuán)隊(duì)可以通過mock所需的數(shù)據(jù)結(jié)構(gòu)來輕松測(cè)試他們的應(yīng)用程序。一旦后端API實(shí)現(xiàn)完成,就可以對(duì)客戶端應(yīng)用程序進(jìn)行切換來調(diào)用實(shí)際的API獲取數(shù)據(jù),這也可以使得我們實(shí)現(xiàn)更好的客戶端和服務(wù)端的分離。
四. GraphQL語法 基礎(chǔ)語法其實(shí)GraphQL所需要學(xué)習(xí)的語法很少,大部分語法與我們平時(shí)的語法一致,可以通過官網(wǎng)詳細(xì)了解。
首先,GraphQL是一門強(qiáng)類型語言,所以和我們?cè)跀?shù)據(jù)庫定義一張表一樣,我們需要定義每一個(gè)屬性的類型.如下圖所示:
下面是一個(gè)簡單的類型定義,先是定義了一個(gè)枚舉,然后我們定義了一個(gè)類型,類型中有四個(gè)屬性:id、 name、 friends、 appearsIn,其中id和name是標(biāo)量類型,而friends是一個(gè)Person類型,這是一個(gè)嵌套類型,仔細(xì)想想應(yīng)該沒什么毛病,畢竟你的朋友和你一樣,都是人,而appearsIn是一個(gè)枚舉類型,看起來還是很熟悉的。
enum Episode { NEWHOPE EMPIRE JEDI } type Person{ id: ID! name: String! friends: [Person] appearsIn: [Episode]! }
了解完類型,再了解一下Arguments和resolver,兩者都是偏服務(wù)端一些,但是了解一下,對(duì)graphql的使用原理有進(jìn)一步的認(rèn)識(shí)。
對(duì)于一個(gè)Restful API來講,除了知道接口URL,我們還需要知道接口的傳參定義,對(duì)于GraphQL其實(shí)也一樣,雖然URL只有一個(gè),不同的接口通過type來區(qū)別,但傳參同Restful API一樣,體現(xiàn)了客戶端與服務(wù)端的交互。
比如下面,查詢的目標(biāo)是id = 2的用戶,獲取他的用戶名:
Query{ user(id: 2) { id userName } }
而在服務(wù)端定義一個(gè)接口時(shí),我們也需要去定義入?yún)ⅲ饕獜膬蓚€(gè)方面,一是類型,二是其是否必填,比如下面這樣:
接口定義user: { type: UserType, args: { id: { type: GraphQLID } }, resolve: (root, args, context, info) => { const { id } = args; return getUser(id); } }查詢定義
上面的代碼只是定義了一個(gè)輸入屬性id,并未定義其是否是必填,所以當(dāng)查詢時(shí),如果沒有配置查詢id,查詢不會(huì)報(bào)錯(cuò),只會(huì)獲取一個(gè)為null的空值結(jié)果。但是講道理的話,我們希望這是一個(gè)必填項(xiàng),所以我們需要修改服務(wù)端的代碼,將id: { type: GraphQLID } 更換為id: {type: new GraphQLNonNull(GraphQLID)},這句代碼的含義就表示id是一個(gè)類型為ID的必填項(xiàng),再次執(zhí)行我們的查詢可以得到下面的錯(cuò)誤提示,提示id是一個(gè)必填的ID類型,同時(shí)右側(cè)也沒有獲取到為空的查詢結(jié)果.
在講上面Arguments時(shí)候,可以零星的看到type中有一個(gè)resolve方法,其接收root, args, context, info四個(gè)參數(shù)。
其中root代表這個(gè)type上父節(jié)點(diǎn)的resolve值(因?yàn)镚raphQL支持嵌套查詢),args就是上面講的,context表在Resolver解析鏈中不斷傳遞的中間變量,和react的上下文相似,而info這個(gè)概念,是當(dāng)前Query的AST對(duì)象,比較抽象,但是可以通過查看info,獲取這個(gè)QUERY的編譯對(duì)象。這個(gè)方法也是后端服務(wù)編寫的重點(diǎn)部分,常常我們可以在這里與已有的Restful API關(guān)聯(lián)起來。
核心概念Schema可以說是GraphQL最具核心的部分,其描述了整個(gè)接口向外暴露的形式。
像Restful API,我們會(huì)定義一個(gè)查詢所有人的接口url定義為:
/api/v1/user/getUsers
查詢?nèi)司唧w信息的接口url為:
/api/v1/user/getUserById
新增一個(gè)人員的接口url定義為:
/api/v1/user/createUser
這樣前端人員調(diào)用起來會(huì)很直觀。
但是graphql是完全不一樣的使用方式,其向前端暴露的url就一個(gè)像/api/graphql之類的,那這么多接口怎么區(qū)分呢? 我們來看看:
奧妙就是上面這張圖,一個(gè)graphql接口都有一個(gè)Schema定義。
其定義三種操作方式:query(查詢),mutation(變更)和subscription(監(jiān)聽)。
再往下延伸,一個(gè)查詢中包含多個(gè)field,也就是多種不同的查詢,比如query user查詢?nèi)耍琿uery message查詢消息,query weather查詢天氣。
通過這些就實(shí)現(xiàn)了Restful API使用多個(gè)url來達(dá)到不同操作的效果。
總結(jié):今天我們只是講了一些GraphQL的基本知識(shí),但我們依然可以看出GraphQL的出現(xiàn)可以使我們后端API具有更大的靈活性以及擴(kuò)展性,滿足了不同client對(duì)數(shù)據(jù)的需要,大大豐富了API的數(shù)據(jù)提供的能力。
部分內(nèi)容來源:https://segmentfault.com/a/11...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/43026.html
摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對(duì)后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會(huì)降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對(duì)后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會(huì)降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:我們知道是一種從服務(wù)器公開數(shù)據(jù)的流行方式。描述所有的可能類型系統(tǒng)基于類型和字段的方式進(jìn)行組織,而非入口端點(diǎn)。因此,需要對(duì)后端進(jìn)行調(diào)整,以滿足新的數(shù)據(jù)需求,這會(huì)降低生產(chǎn)力并顯著降低將用戶反饋集成到產(chǎn)品中的能力。 showImg(https://segmentfault.com/img/remote/1460000017875905?w=2234&h=974); 在前幾天的《StateOf...
摘要:允許創(chuàng)建零配置的服務(wù)器。這是一種人類可讀的模式語法,稱為規(guī)范與描述語言。類型是表示外觀的自定義對(duì)象。為此,創(chuàng)建一個(gè)名為的新查詢。這意味著無論何時(shí)在服務(wù)器中發(fā)生事件,并且每當(dāng)調(diào)用該事件時(shí),服務(wù)器都會(huì)將相應(yīng)的數(shù)據(jù)發(fā)送到客戶端。 showImg(https://segmentfault.com/img/bVbm0c1?w=2560&h=1024); 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,...
摘要:騰訊空間超分辨率技術(shù)為用戶節(jié)省流量,處理效果和速度超谷歌技術(shù)在的標(biāo)準(zhǔn)下,處理速度在提升了,處理效果也有明顯提升。此外,也是業(yè)界首次實(shí)現(xiàn)移動(dòng)端使用深度神經(jīng)網(wǎng)絡(luò)進(jìn)行超分辨率,并保證圖片能夠?qū)崟r(shí)進(jìn)行處理。值得一提的是的對(duì)應(yīng)指標(biāo)也在名單里。 團(tuán)隊(duì)分享 魔幻語言 JavaScript 系列之 call、bind 以及上下文 從一行代碼來看看 JavaScript 是一門多么魔幻的語言,順便談?wù)?...
閱讀 1640·2023-04-25 20:36
閱讀 2049·2021-09-02 15:11
閱讀 1177·2021-08-27 13:13
閱讀 2653·2019-08-30 15:52
閱讀 4589·2019-08-29 17:13
閱讀 1001·2019-08-29 11:09
閱讀 1491·2019-08-26 11:51
閱讀 833·2019-08-26 10:56