
如何快速實(shí)現(xiàn)REST API集成以?xún)?yōu)化業(yè)務(wù)流程
在本文中,我們將以一個(gè)簡(jiǎn)單的博客應(yīng)用為例進(jìn)行說(shuō)明。假設(shè)我們有兩個(gè)模型:用戶(hù)和帖子,它們之間存在一對(duì)多的關(guān)聯(lián)關(guān)系,即一個(gè)用戶(hù)可以發(fā)布多個(gè)帖子。
針對(duì)這個(gè)示例,我們?cè)O(shè)定了以下終端節(jié)點(diǎn):
1. /users
2. /users/<id>
3. /users/<id>/posts
4. /posts
5. /blog/posts/<id>
6. /blog/posts/<id>/user
如果您想使用這個(gè) API,可以查看此存儲(chǔ)庫(kù)中的代碼。
通過(guò)此設(shè)計(jì),我們可以實(shí)現(xiàn)以下查詢(xún)功能:
實(shí)際上,在REST API的設(shè)計(jì)中,返回的數(shù)據(jù)結(jié)構(gòu)主要有兩種表現(xiàn)形式:平面式和嵌套式。
在平面設(shè)計(jì)中,模型間的關(guān)聯(lián)關(guān)系通常通過(guò)相關(guān)項(xiàng)目的ID來(lái)體現(xiàn)。
例如,對(duì)/users
端點(diǎn)的調(diào)用將返回許多用戶(hù)對(duì)象,每個(gè)用戶(hù)對(duì)象都有一個(gè)字段postIds
。此字段包含每個(gè)用戶(hù)關(guān)聯(lián)的帖子的ID數(shù)組:
[
{
"id": "user-0",
"name": "Nikolas",
"postIds": []
},
{
"id": "user-1",
"name": "Sarah",
"postIds": ["post-0", "post-1"]
},
{
"id": "user-2",
"name": "Johnny",
"postIds": ["post-2"]
},
{
"id": "user-3",
"name": "Jenny",
"postIds": ["post-3", "post-4"]
}
]
盡管平面化的API設(shè)計(jì)因其簡(jiǎn)潔明了而備受青睞,但它也可能導(dǎo)致客戶(hù)端面臨N+1請(qǐng)求問(wèn)題:想象一下這樣的場(chǎng)景:客戶(hù)端(如Web應(yīng)用程序)需要展示一個(gè)頁(yè)面,該頁(yè)面需包含用戶(hù)列表及他們最新的文章標(biāo)題。
若采用平面化設(shè)計(jì),你首先需向/users
端點(diǎn)發(fā)送請(qǐng)求,獲取用戶(hù)列表及與他們相關(guān)的帖子ID。隨后,你需為每個(gè)帖子ID單獨(dú)向/blog/posts/<id>
端點(diǎn)發(fā)送請(qǐng)求,以獲取相應(yīng)的標(biāo)題。這種做法不僅效率低下,還可能導(dǎo)致性能瓶頸。
為解決這一問(wèn)題,你可以考慮采用嵌套的API設(shè)計(jì)。在這種設(shè)計(jì)中,每個(gè)user
對(duì)象都會(huì)直接包含一個(gè)posts
數(shù)組,該數(shù)組內(nèi)嵌入了完整的post
對(duì)象,而非僅僅是ID列表。這樣一來(lái),客戶(hù)端便可通過(guò)一次請(qǐng)求即可獲取所有所需信息,從而有效避免N+1請(qǐng)求問(wèn)題。
[
{
"id": "user-0",
"name": "Nikolas",
"posts": []
},
{
"id": "user-1",
"name": "Sarah",
"posts": [
{
"id": "post-0",
"title": "I like GraphQL",
"content": "I really do!",
"published": false
},
{
"id": "post-1",
"title": "GraphQL is better than REST",
"content": "It really is!",
"published": false
}
]
},
{
"id": "user-2",
"name": "Johnny",
"posts": [
{
"id": "post-2",
"title": "GraphQL is awesome!",
"content": "You bet!",
"published": false
}
]
},
{
"id": "user-3",
"name": "Jenny",
"posts": [
{
"id": "post-3",
"title": "Is REST really that bad?",
"content": "Not if you wrap it with GraphQL!",
"published": false
},
{
"id": "post-4",
"title": "I like turtles!",
"content": "...",
"published": false
}
]
}
]
確實(shí),嵌套方法雖然解決了N+1請(qǐng)求問(wèn)題,但它也帶來(lái)了自身的挑戰(zhàn)。對(duì)于包含大型模型對(duì)象的API,帶寬使用(特別是在移動(dòng)設(shè)備上)可能會(huì)成為制約因素。另一個(gè)問(wèn)題是過(guò)度獲取,即客戶(hù)端可能下載了大量并不需要的數(shù)據(jù),從而浪費(fèi)了用戶(hù)的帶寬資源。
此外,即使采用嵌套方法,也不能保證總是能獲得所需的所有數(shù)據(jù)。例如,如果帖子還與評(píng)論相關(guān)聯(lián),并且界面需要顯示每篇文章的最后三條評(píng)論,那么這種嵌套關(guān)系可能會(huì)變得非常復(fù)雜且難以管理。隨著嵌套層級(jí)的增加,每個(gè)層級(jí)都會(huì)帶來(lái)額外的復(fù)雜性和性能開(kāi)銷(xiāo)。
在實(shí)際開(kāi)發(fā)過(guò)程中,我們往往會(huì)發(fā)現(xiàn)終端節(jié)點(diǎn)返回的數(shù)據(jù)是根據(jù)具體應(yīng)用場(chǎng)景來(lái)定制的。這意味著前端團(tuán)隊(duì)會(huì)詳細(xì)列出其數(shù)據(jù)需求,并與后端團(tuán)隊(duì)進(jìn)行溝通,以確保終端節(jié)點(diǎn)返回的有效負(fù)載中包含所有必要的信息。
然而,這種做法在軟件開(kāi)發(fā)流程中帶來(lái)了額外的復(fù)雜性。每當(dāng)前端界面涉及數(shù)據(jù)展示的設(shè)計(jì)發(fā)生變更時(shí),都可能需要后端團(tuán)隊(duì)的直接介入。這不僅會(huì)延長(zhǎng)開(kāi)發(fā)周期,還可能阻礙快速的用戶(hù)反饋和迭代進(jìn)程。
此外,這種方法還存在其他弊端。首先,它非常耗時(shí)且容易出錯(cuò),因?yàn)槊看巫兏夹枰岸撕秃蠖藞F(tuán)隊(duì)的緊密協(xié)作。其次,頻繁變動(dòng)的API很難維護(hù),這不僅增加了后端團(tuán)隊(duì)的工作量,還可能導(dǎo)致客戶(hù)端因數(shù)據(jù)不一致而出現(xiàn)運(yùn)行錯(cuò)誤。特別是當(dāng)某些API響應(yīng)中的字段被刪除而客戶(hù)端未及時(shí)更新時(shí)(或者客戶(hù)端仍在使用較舊的API版本),很可能會(huì)因?yàn)槿鄙俦匾臄?shù)據(jù)而崩潰。
因此,在采用混合布局設(shè)計(jì)REST API時(shí),我們需要謹(jǐn)慎權(quán)衡各種因素。既要確保前端團(tuán)隊(duì)能夠獲得所需的數(shù)據(jù),又要避免給后端團(tuán)隊(duì)帶來(lái)過(guò)大的維護(hù)負(fù)擔(dān),同時(shí)還要確保API的穩(wěn)定性和可靠性。通過(guò)綜合考慮這些因素,我們可以設(shè)計(jì)出既滿足業(yè)務(wù)需求又具有良好擴(kuò)展性和可維護(hù)性的REST API。
GraphQL 能夠有效地解決我們之前提到的N+1問(wèn)題、過(guò)度獲取數(shù)據(jù)以及迭代周期緩慢等挑戰(zhàn)。
GraphQL與REST之間的核心差異可以概括為以下兩點(diǎn):
GraphQL之所以能夠?qū)崿F(xiàn)這一點(diǎn),關(guān)鍵在于客戶(hù)端在請(qǐng)求數(shù)據(jù)時(shí)擁有更大的主動(dòng)權(quán)。客戶(hù)端可以向服務(wù)器提交一個(gè)查詢(xún),明確描述其所需的數(shù)據(jù)結(jié)構(gòu)。服務(wù)器在接收到查詢(xún)后,會(huì)進(jìn)行解析,并僅返回客戶(hù)端明確請(qǐng)求的數(shù)據(jù)。
在GraphQL中,客戶(hù)端通過(guò)發(fā)送查詢(xún)來(lái)指定期望的響應(yīng)結(jié)構(gòu),而這些查詢(xún)將由服務(wù)器進(jìn)行解析。
GraphQL的數(shù)據(jù)查詢(xún)方式在其架構(gòu)定義中得到了明確的規(guī)定。因此,客戶(hù)端無(wú)法請(qǐng)求不存在的字段,從而確保了數(shù)據(jù)的安全性。此外,GraphQL支持查詢(xún)嵌套,這意味著客戶(hù)端可以在單個(gè)請(qǐng)求中同時(shí)獲取相關(guān)聯(lián)項(xiàng)目的信息,從而有效避免了N+1問(wèn)題的發(fā)生。這無(wú)疑是一個(gè)令人稱(chēng)贊的特性!
在本節(jié)中,我們將概述如何通過(guò) 3 個(gè)簡(jiǎn)單的步驟使用 GraphQL 包裝 REST API。
GraphQL其實(shí)并不復(fù)雜!它遵循一些基礎(chǔ)而簡(jiǎn)單的原則,這使得它極具靈活性和廣泛適用性。
構(gòu)建GraphQL API通常包含兩個(gè)核心步驟:首先,您需要定義一個(gè)GraphQL架構(gòu);其次,您需要為這個(gè)架構(gòu)實(shí)現(xiàn)解析器函數(shù)。
這種方法的好處在于其高度的迭代性,這意味著您無(wú)需提前為API規(guī)劃完整的架構(gòu)。相反,您可以根據(jù)實(shí)際需求逐步添加類(lèi)型和字段(這與逐步實(shí)現(xiàn)REST API端點(diǎn)的方式類(lèi)似)。這就是“Schema-driven”或“Schema-First development”的核心理念。
GraphQL解析器函數(shù)的數(shù)據(jù)來(lái)源十分廣泛,可以是從SQL或NoSQL數(shù)據(jù)庫(kù)、REST API、第三方API、遺留系統(tǒng),甚至是其他GraphQL API中獲取。
GraphQL之所以如此靈活,很大程度上是因?yàn)樗⒉灰蕾?lài)于特定的數(shù)據(jù)源。解析器函數(shù)幾乎可以從任何來(lái)源獲取數(shù)據(jù)。
這種特性使得GraphQL成為包裝REST API的理想工具。當(dāng)使用GraphQL包裝REST API時(shí),您需要完成以下三個(gè)步驟:
現(xiàn)在,讓我們以之前的REST API為例,逐步完成這三個(gè)步驟。
您需要了解的第一件事是不同 REST 終端節(jié)點(diǎn)返回的數(shù)據(jù)的形狀。
在我們的示例場(chǎng)景中,我們可以聲明以下內(nèi)容:
User
模型有 id
和 name
字段(字符串類(lèi)型)以及一個(gè)表示與 posts
模型的多對(duì)關(guān)系的 Post
字段。
Post
模型具有 id
、title
、content
(字符串類(lèi)型)和 published
(布爾類(lèi)型)字段以及表示與 author
模型的一對(duì)一關(guān)系的 User
字段。
一旦我們知道了API返回的數(shù)據(jù)的形狀,我們就可以將我們的發(fā)現(xiàn)轉(zhuǎn)化為GraphQL模式定義語(yǔ)言(SDL):
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
published: Boolean!
author: User!
}
SDL語(yǔ)法簡(jiǎn)潔明了。它允許用字段定義類(lèi)型。類(lèi)型上的每個(gè)字段也有一個(gè)類(lèi)型。這可以是標(biāo)量類(lèi)型,如 Int
和 String
,也可以是對(duì)象類(lèi)型,如 Post
和 User
。字段類(lèi)型后面的感嘆號(hào)表示該字段永遠(yuǎn)不能是 null
。
我們?cè)谠撃J街卸x的類(lèi)型將成為我們下一步開(kāi)發(fā)的GraphQL API的基礎(chǔ)。
每個(gè)GraphQL schema都有三種特殊的根類(lèi)型:Query
、Mutation
和 Subscription
。這些類(lèi)型定義了 API 的主要入口點(diǎn),并可以與 REST 端點(diǎn)進(jìn)行某種程度的類(lèi)比(從某種程度上講,REST API 的每個(gè)端點(diǎn)可以被視為一個(gè)針對(duì)其數(shù)據(jù)的查詢(xún),而在 GraphQL 中,Query 類(lèi)型上的每個(gè)字段都代表了一個(gè)可以執(zhí)行的查詢(xún))。
為了定義 GraphQL schema,我們可以采用以下兩種方法中的一種:
在本文中,我們將重點(diǎn)介紹第一種方法,因?yàn)樗軌蚯逦卣故緲?gòu)建 GraphQL schema 的基本步驟。而對(duì)于那些細(xì)心的讀者來(lái)說(shuō),通過(guò)理解這種方法,可以很容易地推斷出第二種方法的工作原理,并作為一個(gè)啟發(fā)性的練習(xí)。
現(xiàn)在,讓我們從 /users
端點(diǎn)開(kāi)始。為了將查詢(xún)用戶(hù)列表的功能添加到我們的 GraphQL API 中,我們需要按照以下步驟操作:
type Query {
users: [User!]!
}
type User {
id: ID!
name: String!
posts: [Post!]!
}
type Post {
id: ID!
title: String!
content: String!
published: Boolean!
author: User!
}
要調(diào)用我們剛剛添加到 GraphQL 模式中的 users
查詢(xún),您可以將以下查詢(xún)語(yǔ)句放入發(fā)送到 GraphQL API 端點(diǎn)的 HTTP POST 請(qǐng)求的主體中:
query {
users {
id
name
}
}
別擔(dān)心,稍后我們會(huì)向您展示如何實(shí)際發(fā)送這個(gè)查詢(xún)。
這里的巧妙之處在于,您在?users
?查詢(xún)下嵌套的字段決定了哪些字段將包含在服務(wù)器響應(yīng)的 JSON 數(shù)據(jù)中。這意味著,如果您在客戶(hù)端上不需要用戶(hù)名,可以簡(jiǎn)單地刪除?name
?字段。更棒的是,如果您愿意,還可以查詢(xún)每個(gè)用戶(hù)的相關(guān)帖子,字段數(shù)量完全由您決定,例如:
query {
users {
id
name
posts {
id
title
}
}
}
現(xiàn)在,讓我們將第二個(gè)端點(diǎn) /users/<id>
添加到我們的 API 中。在 REST API 中作為 URL 參數(shù)的部分,在 GraphQL 中將變成我們?cè)?nbsp;Query
類(lèi)型上引入的字段的參數(shù)(為了簡(jiǎn)潔,這里省略了 User
和 Post
類(lèi)型的詳細(xì)定義,但它們?nèi)匀皇悄J降囊徊糠郑?/p>
type Query {
users: [User!]!
user(id: ID!): User
}
下面是一個(gè)可能的查詢(xún)示例(同樣,我們可以選擇包含?User
?類(lèi)型的任意數(shù)量字段,從而決定服務(wù)器將返回哪些數(shù)據(jù)):
query {
user(id: "user-1") {
name
posts {
title
content
}
}
}
至于 /users/<id>/posts
端點(diǎn),我們實(shí)際上并不需要它,因?yàn)椴樵?xún)特定用戶(hù)的帖子的能力已經(jīng)由剛剛添加的 user(id: ID!): User
字段提供了。這真是太棒了!
現(xiàn)在,讓我們通過(guò)添加查詢(xún)帖子項(xiàng)的功能來(lái)完善我們的 API。我們將為所有相關(guān)的 REST 端點(diǎn)添加對(duì)應(yīng)的查詢(xún):
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
}
就是這樣,我們現(xiàn)在已經(jīng)為 GraphQL API 創(chuàng)建了模式定義,它相當(dāng)于之前的 REST API。接下來(lái),我們需要實(shí)現(xiàn)這些模式的解析器函數(shù),以便能夠處理這些查詢(xún)并返回相應(yīng)的數(shù)據(jù)。
在本教程中,我們主要關(guān)注了查詢(xún),即從服務(wù)器獲取數(shù)據(jù)的操作。然而,在實(shí)際應(yīng)用中,我們經(jīng)常需要更改后端存儲(chǔ)的數(shù)據(jù)。
在使用 REST API 時(shí),我們通常通過(guò)向相同的端點(diǎn)發(fā)送 PUT、POST 和 DELETE HTTP 請(qǐng)求來(lái)完成數(shù)據(jù)的修改。
而在使用 GraphQL 時(shí),我們則通過(guò) Mutation
根類(lèi)型來(lái)處理數(shù)據(jù)的變更。以下是一個(gè)示例,展示了如何向 API 添加創(chuàng)建、更新和刪除用戶(hù)的功能:
type Mutation {
createUser(name: String!): User!
updateUser(id: ID!, name: String!): User
deleteUser(id: ID!): User
}
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
}
請(qǐng)注意,createUser
、updateUser
和 deleteUser
這幾個(gè)突變操作分別對(duì)應(yīng)于傳統(tǒng) REST API 中對(duì) /users
端點(diǎn)或 /users/<id>
端點(diǎn)發(fā)出的 POST、PUT 和 DELETE 請(qǐng)求。為突變操作實(shí)現(xiàn)解析器與處理查詢(xún)的解析器非常相似,因此您無(wú)需為突變學(xué)習(xí)全新的知識(shí)。它們遵循與查詢(xún)相同的機(jī)制,唯一的區(qū)別在于突變解析器可能會(huì)產(chǎn)生副作用,例如修改數(shù)據(jù)庫(kù)中的數(shù)據(jù)。
GraphQL 嚴(yán)格區(qū)分了架構(gòu)的結(jié)構(gòu)和行為。
API 的結(jié)構(gòu)由 GraphQL 架構(gòu)定義語(yǔ)言(SDL)描述。這個(gè)架構(gòu)定義是對(duì) API 功能的抽象描述,它允許客戶(hù)端確切地知道它們可以執(zhí)行哪些操作。
而 GraphQL API 的行為則是通過(guò)解析器函數(shù)來(lái)實(shí)現(xiàn)的,這些函數(shù)為架構(gòu)定義中的每個(gè)字段提供支持,并知道如何獲取該字段的數(shù)據(jù)。
實(shí)現(xiàn)解析器其實(shí)相當(dāng)簡(jiǎn)單。我們只需要調(diào)用相應(yīng)的 REST 端點(diǎn),并返回我們收到的響應(yīng)即可:
const baseURL = https://rest-demo-hyxkwbnhaz.now.sh
const resolvers = {
Query: {
users: () => {
return fetch(${baseURL}/users
).then(res => res.json())
},
user: (parent, args) => {
const { id } = args
return fetch(${baseURL}/users/${id}
).then(res => res.json())
},
posts: () => {
return fetch(${baseURL}/posts
).then(res => res.json())
},
post: (parent, args) => {
const { id } = args
return fetch(${baseURL}/blog/posts/${id}
).then(res => res.json())
},
},
}
對(duì)于 user
和 post
解析器,我們還提取了查詢(xún)中提供的 id
參數(shù),并將其包含在URL中。
現(xiàn)在,要啟動(dòng)并運(yùn)行這個(gè) GraphQL 服務(wù)器,你需要使用 graphql-yoga
(或其他 GraphQL 服務(wù)器庫(kù))來(lái)實(shí)例化一個(gè)服務(wù)器,將解析器和架構(gòu)定義傳遞給它,并調(diào)用 start
方法來(lái)啟動(dòng)服務(wù)器:
const { GraphQLServer } = require('graphql-yoga')
const fetch = require('node-fetch')
const baseURL = https://rest-demo-hyxkwbnhaz.now.sh
const resolvers = {
// ... the resolver implementation from above ...
}
const server = new GraphQLServer({
typeDefs: './src/schema.graphql',
resolvers,
})
server.start(() => console.log(Server is running on http://localhost:4000
))
如果你想跟著這個(gè)教程操作,你可以將上面的?index.js
?和?schema.graphql
?代碼片段復(fù)制到你的 Node.js 項(xiàng)目的?src
?目錄中相應(yīng)的文件中,添加?graphql-yoga
?作為依賴(lài)項(xiàng),然后運(yùn)行?node src/index.js
?來(lái)啟動(dòng)服務(wù)器。
GraphQL Playground 是一個(gè)強(qiáng)大的 GraphQL IDE,它允許你以交互方式探索 GraphQL API 的功能。與 Postman 類(lèi)似,但它提供了許多專(zhuān)為 GraphQL 設(shè)計(jì)的額外功能。在那里,你可以發(fā)送我們之前看到的查詢(xún),并實(shí)時(shí)查看結(jié)果。
查詢(xún)將由 GraphQL 服務(wù)器的 GraphQL 引擎處理。引擎所需要做的就是為查詢(xún)中的每個(gè)字段調(diào)用相應(yīng)的解析器,這些解析器會(huì)調(diào)用適當(dāng)?shù)?REST 端點(diǎn)來(lái)獲取數(shù)據(jù)。
太棒了!現(xiàn)在,你可以根據(jù)需要向查詢(xún)中添加 User
類(lèi)型的字段,并且如果還請(qǐng)求了用戶(hù)的相關(guān) Post
項(xiàng),解析器也會(huì)正確地處理它們。
讓我們?cè)俅慰纯?code>user(id: ID)字段的解析器實(shí)現(xiàn):
user: (parent, args) => {
const { id } = args
return fetch(${baseURL}/users/${id}
).then(res => res.json())
},
在之前的實(shí)現(xiàn)中,我們注意到解析器只返回了從/users/<id>
端點(diǎn)接收的數(shù)據(jù)。由于我們使用的是REST API的平面版本,因此這些數(shù)據(jù)中并沒(méi)有包含與用戶(hù)相關(guān)聯(lián)的帖子(Posts)信息。為了解決這個(gè)問(wèn)題,我們需要為User
類(lèi)型實(shí)現(xiàn)一個(gè)專(zhuān)用的解析器,來(lái)獲取用戶(hù)的所有帖子。同樣地,我們也需要為Post
類(lèi)型實(shí)現(xiàn)一個(gè)解析器,來(lái)獲取帖子的作者(User)信息。
下面是更新后的解析器實(shí)現(xiàn):
const resolvers = {
Query: {
// ... the resolver implementation from above ...
},
Post: {
author: parent => {
const { id } = parent
return fetch(${baseURL}/blog/posts/${id}/user
).then(res => res.json())
},
},
User: {
posts: parent => {
const { id } = parent
return fetch(${baseURL}/users/${id}/posts
).then(res => res.json())
},
},
}
現(xiàn)在,解析器的實(shí)現(xiàn)已經(jīng)能夠處理嵌套查詢(xún)了
你已經(jīng)成功地學(xué)會(huì)了如何使用GraphQL來(lái)包裝現(xiàn)有的REST API,并為其添加關(guān)聯(lián)數(shù)據(jù)的處理能力。現(xiàn)在,你可以根據(jù)需要擴(kuò)展你的GraphQL API,以支持更復(fù)雜的查詢(xún)和數(shù)據(jù)關(guān)系。
在本文中,我們僅初步探討了使用 GraphQL 包裝 REST API 的潛力。為了更全面地理解這一領(lǐng)域,我們接下來(lái)將簡(jiǎn)要介紹一些在現(xiàn)代 API 開(kāi)發(fā)中至關(guān)重要的更高級(jí)主題。
REST API 通常具備明確的身份驗(yàn)證和授權(quán)流程。每個(gè) API 端點(diǎn)都會(huì)設(shè)定特定的訪問(wèn)要求,只有滿足這些要求的客戶(hù)端才能成功訪問(wèn)。在 HTTP 請(qǐng)求中,客戶(hù)端通常會(huì)攜帶一個(gè)身份驗(yàn)證令牌,用于驗(yàn)證其身份并獲取訪問(wèn)權(quán)限。
當(dāng)我們將 REST API 包裝在 GraphQL 之下時(shí),這一流程依然適用。攜帶 GraphQL 查詢(xún)的 HTTP 請(qǐng)求同樣需要包含身份驗(yàn)證令牌。在 GraphQL 服務(wù)器處理請(qǐng)求時(shí),它會(huì)將這個(gè)令牌附加到底層 REST API 調(diào)用的相應(yīng)標(biāo)頭中,以確保請(qǐng)求能夠成功通過(guò)身份驗(yàn)證和授權(quán)檢查。
在之前的討論中,我們可能已經(jīng)注意到,雖然 GraphQL 能夠減少客戶(hù)端發(fā)出的請(qǐng)求數(shù)量(從而解決 N+1 請(qǐng)求問(wèn)題),但 GraphQL 服務(wù)器仍然需要執(zhí)行與客戶(hù)端原本需要發(fā)出的請(qǐng)求數(shù)量相同的 REST 調(diào)用。然而,這種轉(zhuǎn)變?nèi)匀粠?lái)了性能上的提升,因?yàn)榉?wù)器更適合處理這種繁重的工作,特別是在網(wǎng)絡(luò)條件不穩(wěn)定的情況下。
為了進(jìn)一步提升性能,我們可以引入 Data Loader 模式來(lái)實(shí)現(xiàn)并行化。通過(guò)這一模式,我們可以將解析器調(diào)用進(jìn)行批處理,并使用專(zhuān)用的批處理函數(shù)來(lái)更高效地檢索數(shù)據(jù),這種方法能夠顯著減少數(shù)據(jù)檢索所需的時(shí)間,從而提升整體性能。
在現(xiàn)代應(yīng)用程序中,實(shí)時(shí)更新已經(jīng)成為了一個(gè)重要的功能需求。GraphQL 提供了訂閱功能,允許客戶(hù)端訂閱服務(wù)器端發(fā)生的特定事件。與 GraphQL 查詢(xún)和變更操作類(lèi)似,我們也可以使用 GraphQL 訂閱來(lái)包裝實(shí)時(shí) API(例如基于 WebSocket 的 API)。這將使客戶(hù)端能夠?qū)崟r(shí)接收服務(wù)器端的數(shù)據(jù)更新,從而提供更加流暢和動(dòng)態(tài)的用戶(hù)體驗(yàn)。我們將在后續(xù)的文章中深入探討這一話題,敬請(qǐng)期待!
在本文中,您學(xué)習(xí)了如何通過(guò)三個(gè)簡(jiǎn)單的步驟將 REST API 轉(zhuǎn)換為 GraphQL API:
使用 GraphQL 包裝 REST API 是 GraphQL 最具潛力的應(yīng)用場(chǎng)景之一,盡管這一領(lǐng)域仍處于起步階段。值得注意的是,本文中介紹的過(guò)程是手動(dòng)的。然而,自動(dòng)化這些步驟才是真正實(shí)現(xiàn)這一技術(shù)潛力的關(guān)鍵所在。因此,我們期待在未來(lái)能夠探索更多關(guān)于自動(dòng)化這一過(guò)程的想法和解決方案。
如果您希望進(jìn)一步探索這一領(lǐng)域,您可以考慮查看 graphql-binding-openapi 包。這個(gè)包允許您基于 Swagger/Open API 規(guī)范自動(dòng)生成 GraphQL API(以 GraphQL 綁定的形式)。這將為您提供一個(gè)更加高效和便捷的方式來(lái)將 REST API 轉(zhuǎn)換為 GraphQL API。
原文鏈接:https://www.prisma.io/blog/how-to-wrap-a-rest-api-with-graphql-8bf3fb17547d
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)