在許多情況下,您不想要從 API 傳回數字或字串。您想要傳回一個具有其自身複雜行為的物件。GraphQL 非常適合這種情況。
在 GraphQL 結構語言中,定義新物件類型的步驟與我們在範例中定義 Query
類型的步驟相同。每個物件都可以有傳回特定類型的欄位,以及接收參數的方法。例如,在 傳遞參數 文件中,我們有一個方法可以擲出一些隨機骰子
type Query { rollDice(numDice: Int!, numSides: Int): [Int]}
如果我們想要隨著時間推移,根據隨機骰子建立越來越多的方法,我們可以使用 RandomDie
物件類型來實作它。
type RandomDie { roll(numRolls: Int!): [Int]}
type Query { getDie(numSides: Int): RandomDie}
對於 RandomDie
類型,我們可以使用 ES6 類別,而不是根層解析器,其中解析器是實例方法。此程式碼顯示如何實作上述 RandomDie
結構
class RandomDie { constructor(numSides) { this.numSides = numSides }
rollOnce() { return 1 + Math.floor(Math.random() * this.numSides) }
roll({ numRolls }) { var output = [] for (var i = 0; i < numRolls; i++) { output.push(this.rollOnce()) } return output }}
var root = { getDie: ({ numSides }) => { return new RandomDie(numSides || 6) },}
對於不使用任何參數的欄位,您可以使用物件或實例方法上的屬性。因此,對於上述範例程式碼,numSides
和 rollOnce
實際上都可以用來實作 GraphQL 欄位,因此該程式碼也實作了
type RandomDie { numSides: Int! rollOnce: Int! roll(numRolls: Int!): [Int]}
type Query { getDie(numSides: Int): RandomDie}
將所有這些放在一起,以下是執行具有此 GraphQL API 的伺服器的範例程式碼
var express = require("express")var { createHandler } = require("graphql-http/lib/use/express")var { buildSchema } = require("graphql")
// Construct a schema, using GraphQL schema languagevar schema = buildSchema(` type RandomDie { numSides: Int! rollOnce: Int! roll(numRolls: Int!): [Int] }
type Query { getDie(numSides: Int): RandomDie }`)
// This class implements the RandomDie GraphQL typeclass RandomDie { constructor(numSides) { this.numSides = numSides }
rollOnce() { return 1 + Math.floor(Math.random() * this.numSides) }
roll({ numRolls }) { var output = [] for (var i = 0; i < numRolls; i++) { output.push(this.rollOnce()) } return output }}
// The root provides the top-level API endpointsvar root = { getDie: ({ numSides }) => { return new RandomDie(numSides || 6) },}
var app = express()app.all( "/graphql", createHandler({ schema: schema, rootValue: root, }))app.listen(4000)console.log("Running a GraphQL API server at localhost:4000/graphql")
當你對傳回物件類型的 API 發出 GraphQL 查詢時,你可以透過巢狀 GraphQL 欄位名稱一次呼叫物件上的多個方法。例如,如果你想要呼叫 rollOnce
來擲骰子一次,以及 roll
來擲骰子三次,你可以使用這個查詢來執行
{ getDie(numSides: 6) { rollOnce roll(numRolls: 3) }}
如果你使用 node server.js
執行此程式碼並瀏覽至 http://localhost:4000/graphql,你可以使用 GraphiQL 試用這些 API。
這種定義物件類型的做法通常比傳統的 REST API 具有優勢。你不需要先執行一個 API 要求來取得物件的基本資訊,然後再執行多個後續的 API 要求來找出關於該物件的更多資訊,你可以一次在一個 API 要求中取得所有資訊。這可以節省頻寬、讓你的應用程式執行得更快,並簡化你的用戶端邏輯。
到目前為止,我們看過的每個 API 都是設計用來傳回資料。為了修改儲存的資料或處理複雜的輸入,建議你瞭解變異和輸入類型。