2021-03-13 分類: 網(wǎng)站建設(shè)
通常情況下,GraphQL被視作一種革命性的對(duì)于API查詢方式的思考,您可以發(fā)送查詢,以便在一個(gè)請(qǐng)求中準(zhǔn)確獲取要查找的數(shù)據(jù),而無需使用嚴(yán)格的服務(wù)器端定義。事實(shí)確實(shí)如此 - 當(dāng)組織采用GraphQL時(shí),它可以具有變革性,使前端和后端團(tuán)隊(duì)能夠比以前更順利地進(jìn)行協(xié)作。 但實(shí)際上,這兩種技術(shù)都涉及發(fā)送HTTP請(qǐng)求并接收一些結(jié)果,并且GraphQL包含許多內(nèi)置的REST模型元素。
那么技術(shù)層面上真正發(fā)生了什么? 這兩個(gè)API范例有什么相似之處和不同之處? 本文末尾的聲明是,GraphQL和REST其實(shí)沒有太大的不同,但是GraphQL有一些小的改變,這對(duì)開發(fā)者構(gòu)建和使用API的體驗(yàn)產(chǎn)生了很大的影響。
因此,讓我們直接進(jìn)入。我們將定義一些API屬性,然后討論GraphQL和REST如何處理它們。
REST的核心思想是資源。 每個(gè)資源都由一個(gè)URL標(biāo)識(shí),并通過向該URL發(fā)送GET請(qǐng)求來檢索該資源。 你可能會(huì)得到一個(gè)JSON響應(yīng),因?yàn)檫@是大多數(shù)API現(xiàn)在使用的。 所以它看起來像這樣:
GET /books/1
{ "title": "Black Hole Blues", "author": { "firstName": "Janna", "lastName": "Levin" } // ... more fields here}
Note: 在上面的示例中,一些REST API會(huì)將“author”作為單獨(dú)的資源返回.
在REST中需要注意的一點(diǎn)是,資源的類型或形狀以及您獲取資源的方式是耦合的。 當(dāng)您在REST文檔中討論上述內(nèi)容時(shí),您可能會(huì)將其稱為“book endpoint”.
GraphQL在這方面完全不同,因?yàn)樵贕raphQL中,這兩個(gè)概念是完全分離的。 在您的模式中,您可能有Book和Author類型:
type Book { id: ID title: String published: Date price: String author: Author}
type Author { id: ID firstName: String lastName: String books: [Book]}
請(qǐng)注意,我們所描述的各種數(shù)據(jù)可用,但這種描述不會(huì)告訴你任何關(guān)于如何在客戶端獲取這些對(duì)象。 這是REST和GraphQL的核心區(qū)別 - 特定資源的描述與您檢索它的方式不相關(guān)。
為了能夠?qū)嶋H訪問特定的book或author,我們需要在我們的模式中創(chuàng)建一個(gè)Query類型:
type Query { book(id: ID!): Book author(id: ID!): Author}
現(xiàn)在,我們可以發(fā)送類似于上面的REST請(qǐng)求的請(qǐng)求,但是這次使用GraphQL:
GET /graphql?query={ book(id: "1") { title, author { firstName } } }
{ "title": "Black Hole Blues", "author": { "firstName": "Janna", }}
很好,現(xiàn)在我們到了某一步! 我們可以立即看到有關(guān)GraphQL的一些與REST完全不同的內(nèi)容,即使兩者都可以通過URL請(qǐng)求,并且兩者都可以返回相同形式的JSON響應(yīng)。
首先,我們可以看到帶有GraphQL查詢的URL指定了我們要求的資源以及我們關(guān)心的是哪些字段。 另外,API的使用者決定,而不是服務(wù)器作者為我們決定需要包含相關(guān)author資源。
但最重要的是,資源的標(biāo)識(shí),book和author的概念,并沒有與它們被獲取的方式相聯(lián)系。 我們可以通過許多不同類型的查詢以及不同的字段來檢索相同的Book。
我們已經(jīng)確定了一些相似之處和差異:
好的,如果你已經(jīng)使用了非?;A(chǔ)的GraphQL和/或REST, 如果你之前沒有使用過GraphQL,你可以在Launchpad里面玩一玩 an example similar to the above ,Launchpad是一款用于在您的瀏覽器中構(gòu)建和探索GraphQL示例的工具。
如果API不可預(yù)測(cè),則該API無用。 當(dāng)你使用一個(gè)API時(shí),你通常將它作為某個(gè)程序的一部分來執(zhí)行,并且該程序需要知道它可以調(diào)用的內(nèi)容以及它應(yīng)該期望得到的結(jié)果,以便它可以運(yùn)行得出結(jié)果。
因此,API中最重要的部分之一是對(duì)可訪問內(nèi)容的描述。 這是您在閱讀API文檔時(shí)學(xué)習(xí)的內(nèi)容,以及使用Graphql自檢和Rag API架構(gòu)系統(tǒng)(如Swagger)時(shí),可以通過編程方式檢查此信息。
在當(dāng)今的REST API中,API通常被描述為一個(gè)端點(diǎn)列表:
GET /books/:idGET /authors/:idGET /books/:id/commentsPOST /books/:id/comments
所以你可以說API的“形狀”是線性的 - 有一系列你可以訪問的東西。 當(dāng)您檢索數(shù)據(jù)或保存某些內(nèi)容時(shí),首先要問的問題是“我應(yīng)該調(diào)用哪個(gè)端”?
在GraphQL中,如上所述,您不使用URL來標(biāo)識(shí)API中可用的內(nèi)容。 相反,您使用GraphQL模式:
type Query { book(id: ID!): Book author(id: ID!): Author}
type Mutation { addComment(input: AddCommentInput): Comment}
type Book { ... }type Author { ... }type Comment { ... }input AddCommentInput { ... }
與類似數(shù)據(jù)集的REST路由相比,這里有一些有趣的地方。 首先,不是將一個(gè)不同的HTTP動(dòng)詞發(fā)送到相同的URL來區(qū)分讀取和寫入,而是使用不同的 initial type --- Mutation vs. Query。 在GraphQL文檔中,您可以選擇使用關(guān)鍵字發(fā)送哪種類型的操作:
query { ... }mutation { ... }
有關(guān)查詢語言的所有細(xì)節(jié),請(qǐng)閱讀我之前的文章, “GraphQL查詢的解析”
你可以看到Query類型的字段與我們上面的REST路由很好地匹配。 這是因?yàn)檫@種特殊類型是我們數(shù)據(jù)的入口點(diǎn),所以這是GraphQL中與端點(diǎn)URL最相同的概念。
您從GraphQL API獲取初始資源的方式與REST非常相似 - 您傳遞了一個(gè)名稱和一些參數(shù) - 但主要區(qū)別在于您可以從那里開始。 在GraphQL中,您可以發(fā)送一個(gè)復(fù)雜查詢,根據(jù)模式中定義的關(guān)系獲取其他數(shù)據(jù),但在REST中,您必須通過多個(gè)請(qǐng)求來完成此操作,將相關(guān)數(shù)據(jù)構(gòu)建到初始響應(yīng)中,或者在 修改響應(yīng)的URL。
在REST中,可訪問數(shù)據(jù)的空間被描述為一個(gè)線性的端點(diǎn)列表,在GraphQL中它是一個(gè)包含關(guān)系的模式。
由于上述相似性列表中的第一點(diǎn),人們經(jīng)常開始將Query類型的字段稱為GraphQL“端點(diǎn)”或“查詢”。 盡管這是一個(gè)合理的比較,但它可能會(huì)導(dǎo)致誤導(dǎo)性的觀點(diǎn),即查詢類型與其他類型顯著不同,而事實(shí)并非如此。
那么當(dāng)你實(shí)際調(diào)用API時(shí)會(huì)發(fā)生什么? 那么,通常它會(huì)在接收請(qǐng)求的服務(wù)器上執(zhí)行一些代碼。 該代碼可以執(zhí)行計(jì)算,從數(shù)據(jù)庫加載數(shù)據(jù),調(diào)用不同的API,或者真的做任何事情。 整個(gè)想法是你不需要從外面知道它在做什么。 但是REST和GraphQL都有相當(dāng)標(biāo)準(zhǔn)的方法來實(shí)現(xiàn)該API的內(nèi)部,并且將它們進(jìn)行比較以了解這些技術(shù)是如何不同的。
在這個(gè)比較中,我將使用JavaScript代碼,因?yàn)檫@是我最熟悉的,但是當(dāng)然,您可以在幾乎任何編程語言中實(shí)現(xiàn)REST和GraphQL API。 我也會(huì)跳過設(shè)置服務(wù)器所需的任何樣板文件,因?yàn)檫@對(duì)概念并不重要。
讓我們來看一下hello world中的一個(gè)快速示例,一個(gè)用于Node的流行API庫:
app.get('/hello', function (req, res) {
res.send('Hello World!')
})
在這里你看到我們已經(jīng)創(chuàng)建了一個(gè)返回字符串'Hello World!'的/hello端點(diǎn)。 從這個(gè)例子中,我們可以看到REST API服務(wù)器中HTTP請(qǐng)求的生命周期:
GraphQL的工作方式非常類似,也是相同的hello world example
const resolvers = { Query: { hello: () => { return 'Hello world!';
}, },};
正如你所看到的,我們不是為某個(gè)特定的URL提供一個(gè)函數(shù),而是提供了一個(gè)匹配某個(gè)類型的特定字段的函數(shù),在這種情況下,這個(gè)函數(shù)是Query類型的hello字段。 在GraphQL中,實(shí)現(xiàn)字段的這個(gè)函數(shù)被稱為 解析器。
為了發(fā)出請(qǐng)求,我們需要一個(gè)查詢:
query { hello}
因此,當(dāng)我們的服務(wù)器收到一個(gè)GraphQL請(qǐng)求時(shí)會(huì)發(fā)生什么情況:
所以你會(huì)接收到:
{ "hello": "Hello, world!" }
但是這里有一個(gè)技巧,我們實(shí)際上可以調(diào)用兩次這個(gè)Query!
query { hello secondHello: hello}
在這種情況下,同樣的生命周期發(fā)生在上面,但由于我們使用別名請(qǐng)求了兩次相同的字段,所以hello解析器實(shí)際上稱為twice。 這顯然是一個(gè)人為的例子,但重點(diǎn)是可以在一個(gè)請(qǐng)求中執(zhí)行多個(gè)字段,并且可以在查詢中的不同點(diǎn)處多次調(diào)用同一個(gè)字段。
沒有“嵌套”解析器的例子,這將是不完整的:
{ Query: { author: (root, { id }) => find(authors, { id: id }), }, Author: { posts: (author) => filter(posts, { authorId: author.id }), },}
這些解析器將能夠完成如下查詢:
query { author(id: 1) { firstName posts { title } }}
所以即使解析器的集合實(shí)際上是平坦的,因?yàn)樗鼈儽桓郊拥礁鞣N類型,您可以將它們構(gòu)建為嵌套查詢。在帖子中閱讀更多關(guān)于GraphQL執(zhí)行如何工作的信息 “GraphQL 解釋”.
在這一天結(jié)束時(shí),REST和GraphQL API都是通過網(wǎng)絡(luò)調(diào)用功能的奇特方式。 如果您熟悉構(gòu)建REST API,那么實(shí)施GraphQL API不會(huì)有太大的不同。 但是GraphQL有很大的優(yōu)勢(shì),因?yàn)樗梢宰屇阏{(diào)用幾個(gè)相關(guān)的函數(shù)而不需要多次往返。
從本質(zhì)上講,您可以將GraphQL想象成一個(gè)在一個(gè)請(qǐng)求中調(diào)用多個(gè)嵌套端點(diǎn)的系統(tǒng)。 幾乎就像一個(gè)多路復(fù)用的REST。
在這篇特別的文章中,我們沒有太多空間可以參與。 例如,對(duì)象標(biāo)識(shí),超媒體或高速緩存。 也許這將是以后的一個(gè)話題。 但是我希望你們同意,當(dāng)你看一看基本的知識(shí)時(shí),REST和GraphQL正在使用基本相似的概念。
我認(rèn)為GraphQL有一些差異。 特別是,我認(rèn)為能夠?qū)⒛腁PI作為一組小的解析器函數(shù)實(shí)現(xiàn)是非??岬?,然后有能力發(fā)送一個(gè)復(fù)雜的查詢,以可預(yù)測(cè)的方式一次檢索多個(gè)資源。 這節(jié)省了API實(shí)現(xiàn)者不必創(chuàng)建具有特定形狀的多個(gè)端點(diǎn),并且使得API消費(fèi)者能夠避免獲取他們不需要的額外數(shù)據(jù)。
另一方面,GraphQL沒有REST那么多的工具和集成。 例如,您無法像使用REST結(jié)果一樣輕松地緩存使用HTTP緩存的GraphQL結(jié)果。 但社區(qū)正在努力改善工具和基礎(chǔ)設(shè)施。 例如,您可以使用Apollo Client和Relay在您的前端緩存GraphQL結(jié)果,最近也可以在服務(wù)器上使用Apollo Engine.緩存GraphQL結(jié)果。
文章標(biāo)題:Rest相比GraphQL有什么好處?
轉(zhuǎn)載注明:http://jinyejixie.com/news33/105133.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、服務(wù)器托管、小程序開發(fā)、靜態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容