GraphQL和REST有什麼不同?
- GraphQL
- Rest
一、概述
在創建 Web 服務來支持我們的應用程序時,我們可能會選擇使用 REST 或 GraphQL 作為通信模式。雖然兩者都最有可能在 HTTP 上使用 JSON,但它們有不同的優點和缺點。
在本教程中,我們將比較 GraphQL 和 REST。我們將創建一個產品數據庫示例,並比較兩種解決方案在執行相同的客戶端操作時有何不同。
2. 示例服務
我們的示例服務將允許我們:
- 創建處於草稿狀態的產品
- 更新產品詳情
- 獲取產品列表
- 獲取單個產品的詳細信息及其訂單
讓我們從使用 REST 創建應用程序開始。
3.REST
REST(Representational State Transfer)是一種分佈式超媒體系統的架構風格。 REST 中的主要數據元素稱為Resource 。在此示例中,資源是“product”
。
3.1創建產品
要創建產品,我們將在 API 上使用POST
方法:
curl -X POST -H "Content-Type:application/json" -d '
{
"name": "Watch",
"description": "Special Swiss Watch",
"status": "Draft",
"currency": "USD",
"price": null,
"image_url": null,
"video_url": null,
"stock": null,
"average_rating": null
}' https://graphqlvsrest.com/product
結果,系統將創建一個新產品。
3.2更新產品
在 REST 中,我們通常使用PUT
方法更新產品:
curl -X PUT -H "Content-Type:application/json" -d '
{
"name": "Watch",
"description": "Special Swiss Watch",
"status": "Draft",
"currency": "USD",
"price": 1200.0,
"image_url": ["https://graphqlvsrest.com/imageurl/product-id"],
"video_url": ["https://graphqlvsrest.com/videourl/product-id"],
"stock": 10,
"average_rating": 0.0
}'
https://graphqlvsrest.com/product/{product-id}
因此, {product-id}
對象會有更新。
3.3獲取產品列表
列出產品通常是一個GET
操作,我們可以使用查詢字符串來指定分頁:
curl -X GET https://graphqlvsrest.com/product?size=10&page=0
第一個響應對像是:
{
"id": 1,
"name": "T-Shirt",
"description": "Special beach T-Shirt",
"status": Published,
"currency": "USD",
"price": 30.0,
"image_url": ["https://graphqlvsrest.com/imageurl/1"],
"video_url": ["https://graphqlvsrest.com/videourl/1"],
"stock": 10,
"average_rating": 3.5
}
3.4通過訂單獲取單個產品
要獲取產品及其訂單,我們通常希望使用之前的 API 獲取產品列表,然後調用orde
r
以查找相關訂單:
curl -X GET https://graphqlvsrest.com/order?product-id=1
第一個響應對像是:
{
"id": 1,
"product_id": 1,
"customer_uuid": "de68a771-2fcc-4e6b-a05d-e30a8dd0d756",
"status": "Delivered",
"address": "43-F 12th Street",
"creation_date": "Mon Jan 17 01:00:18 GST 2022"
}
當我們通過product-id
查詢訂單時,將 id 作為查詢參數提供給GET
操作是有意義的。但是,我們應該注意,除了原始操作以獲取所有產品之外,我們還需要對我們感興趣的每個產品執行一次此操作。這與N + 1 Select Problem
相關。
4.GraphQL
GraphQL 是一種用於 API 的查詢語言,它帶有一個運行時,用於使用現有數據服務來完成這些查詢。
GraphQL 的構建塊是查詢和突變。查詢負責獲取數據,而突變用於創建和更新。
查詢和變異都定義了一個模式。模式定義了可能的客戶端請求和響應。
讓我們使用 GraphQL Server 重新實現我們的示例。
4.1創建產品
讓我們使用一個名為saveProduct
的突變:
curl -X POST -H "Content-Type:application/json" -d'
{
"query": "mutation {saveProduct (
product: {
name: \"Bed-Side Lamp\",
price: 24.0,
status: \"Draft\",
currency: \"USD\"
}){ id name currency price status}
}"
}'
https://graphqlvsrest.com/graphql
在這個saveProduct
函數中,圓括號內的所有內容都是輸入類型schema 。後面的大括號描述了服務器要返回的字段。
當我們運行突變時,我們應該期待一個帶有所選字段的響應:
{
"data": {
"saveProduct": {
"id": "12",
"name": "Bed-Side Lamp",
"currency": "USD",
"price": 24.0,
"status": "Draft"
}
}
}
這個請求與我們使用 REST 版本發出的 POST 請求非常相似,儘管我們現在可以稍微自定義響應。
4.2更新產品
同樣,我們可以使用另一個名為updateProduct
的突變來修改產品:
curl -X POST -H "Content-Type:application/json" -d'
{
"query": "mutation {updateProduct (id:12
product: {
price: 14.0,
status: \"Publish\"
}){ id name currency price, status}
}"
}'
https://graphqlvsrest.com/graphql
我們在響應中收到選擇的字段:
{
"data": {
"updateProduct": {
"id": "12",
"name": "Bed-Side Lamp",
"currency": "USD",
"price": 14.0,
"status": "Published"
}
}
}
正如我們所見, GraphQL 提供了響應格式的靈活性。
4.3獲取產品列表
要從服務器獲取數據,我們將使用查詢:
curl -X POST -H "Content-Type:application/json" -d
'{
"query": "query {products(size:10,page:0){ id name status}}"
}'
https://graphqlvsrest.com/graphql
在這裡,我們還描述了我們希望看到的結果頁面:
{
"data": {
"products": [
{
"id": "1",
"name": "T-Shirt",
"status": "Published"
},...
]
}
}
4.4.通過訂單獲取單個產品
使用 GraphQL,我們可以要求 GraphQL 服務器將產品和訂單連接在一起:
curl -X POST -H "Content-Type:application/json" -d
'{
"query": "query {product(id:1){ id name orders{customer_uuid address status creation_date}}}"
}'
https://graphqlvsrest.com/graphql
在此查詢中,我們獲取id
等於 1 的產品及其訂單。這使我們能夠在單個操作中發出請求,讓我們檢查響應:
{
"data": {
"product": {
"id": "1",
"name": "T-Shirt",
"orders": [
{
"customer_uuid": "de68a771-2fcc-4e6b-a05d-e30a8dd0d756",
"status": "Delivered",
"address": "43-F 12th Street",
"creation_date": "Mon Jan 17 01:00:18 GST 2022"
}, ...
]
}
}
}
正如我們在此處看到的,響應包含產品的詳細信息及其各自的訂單。
為了使用 REST 實現這一點,我們需要發送幾個請求——第一個請求獲取產品,第二個請求獲取相應的訂單。
5.比較
這些示例展示了 GraphQL 如何減少客戶端和服務器之間的流量,並允許客戶端為響應提供一些格式化規則。
值得注意的是,這些 API 背後的數據源可能仍然需要執行相同的操作來修改或獲取數據,但客戶端和服務器之間的豐富接口允許客戶端使用 GraphQL 做更少的工作。
讓我們進一步比較這兩種方法。
5.1.性能更好
每個服務器請求都有往返時間和有效負載大小的代價。
在 REST 中,我們最終可能會發送多個請求以實現所需的功能。這些多個請求將是一項昂貴的操作。此外,響應負載可能包含客戶端應用程序可能不需要的不必要數據。
GraphQL 傾向於避免昂貴的操作。我們通常可以使用 GraphQL 在單個請求中獲取我們需要的所有數據。
5.2靈活和動態的查詢
GraphQL 允許靈活和動態的查詢:
- 客戶端應用程序只能請求必填字段
- 別名可用於請求具有自定義鍵的字段
- 客戶端可以使用查詢來管理結果順序
- 客戶端可以更好地與 API 中的任何更改分離,因為沒有單一版本的響應對象結構可以遵循
5.3.何時使用 REST?
GraphQL 不是 REST 的替代品。兩者甚至可以在同一個應用程序中共存。託管 GraphQL 端點的複雜性增加可能是值得的,具體取決於用例。
在以下情況下,我們可能更喜歡 REST:
- 我們的應用程序自然是資源驅動的,其中操作與各個資源實體非常直接且完全相關聯
- 需要 Web 緩存,因為 GraphQL 本身並不支持它
- 我們需要文件上傳,因為 GraphQL 本身不支持它
六,結論
在本文中,我們使用一個實際示例比較了 REST 和 GraphQL。我們看到了我們如何按照慣例使用所學的每種方法。
然後,我們討論了這兩種方法如何比另一種方法具有明顯的優勢。我們的要求將是在它們之間做出選擇的驅動力。有時,兩者也可以共存。