介紹:GraphQL服務(wù)端開發(fā)

本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列机断。

每個GraphQL API的核心:GraphQL schema

schema中的類型定義了API操作

每個GraphQL API的核心是GraphQL schema,它清楚地定義了所有可用的API操作和數(shù)據(jù)類型僧家。schema使用稱為模式定義語言(Schema Define Language,SDL)的專用語法編寫鱼喉。 SDL簡潔易用摊唇。

下面是一個演示如何定義簡單的User類型的例子左医,該User有兩個字段,即idname特姐。

type User {
  id: ID!
  name: String!
}

每個GraphQL schema都有三種特殊的根類型晶丘,稱為查詢(Query),突變(Mutation)和訂閱(Subscription)。這些根類型的字段定義了API接受的操作。

作為示例谎砾,請考慮以下Query和Mutation類型:

type Query {
  users: [User!]!
}

type Mutation {
  createUser(name: String!): User!
}

此schema定義的GraphQL API將允許執(zhí)行以下兩項操作:

# 查詢用戶列表
query {
  users {
    id
    name
  }
}

# 創(chuàng)建新用戶
mutation {
  createUser(name: "Sarah") {
    id
  }
}

查詢(Query) / 突變(Mutation)內(nèi)的所有字段及其參數(shù)的集合稱為操作的選擇集(selection set)摔竿。

根字段定義API的入口點(entry-points)

根類型上的字段也稱為根字段(root fields)睬关,并為API提供入口點(entry-points)。這意味著發(fā)送到API的查詢(Query) / 突變(Mutation)總是需要以其中一個根字段開始。

根字段的類型(type)確定哪些字段可以進一步包含在查詢的選擇集中。在上面的例子中郁油,類型是User[User!]!在這兩種情況下都允許包含User類型的任何字段。

如果根字段具有標量(scalar)類型攀痊,則不可能在選擇集中包含任何其他字段桐腌。作為示例,請考慮以下GraphQL schema:

type Query {
  hello: String!
}

此查詢定義的GraphQL API只接受一個hello操作:

query {
  hello
}

解析器函數(shù)(Resolver functions)實現(xiàn)schema

GraphQL服務(wù)中的結(jié)構(gòu)與行為

GraphQL具有明確分離的結(jié)構(gòu)(structure)和行為(behaviour)苟径。雖然SDL schema定義僅描述了API的抽象結(jié)構(gòu)(abstract structure)案站,但具體實現(xiàn)是通過所謂的解析器功能(Resolver functions)實現(xiàn)的。schema定義和解析器(resolver)實現(xiàn)的組合通常被稱為可執(zhí)行schema(executable schema)棘街。

GraphQL schema中的每個字段都由一個解析器函數(shù)支持蟆盐,這意味著解析器函數(shù)與GraphQL schema中的字段一樣多(包括除根類型之外的其他類型的字段)。

他為某個領(lǐng)域的解析器功能負責(zé)為該領(lǐng)域準確提取數(shù)據(jù)遭殉。例如石挂,上面的用戶root字段的解析器知道如何獲取用戶列表。

字段的解析器函數(shù)負責(zé)為該字段準確提取數(shù)據(jù)恩沽。例如誊稚,上面的user 根字段的解析器知道如何獲取用戶列表翔始。

因此罗心,GraphQL查詢解析的過程其實是調(diào)用查詢中包含的字段的解析器函數(shù)的操作,因為每個解析器都會為其字段返回數(shù)據(jù)城瞎。

解析器函數(shù)(Resolver functions)剖析

解析器函數(shù)總是需要四個參數(shù)(按以下順序):

  • parent (有時也稱為root) :查詢由GraphQL引擎解析渤闷,該引擎調(diào)用查詢中包含的字段的解析器。因為查詢可以包含嵌套字段脖镀,所以可能會有多級解析器執(zhí)行飒箭。parent 參數(shù)始終表示前一個解析器調(diào)用的返回值。請參閱此處了解更多信息。
  • args:為該字段提供的潛在參數(shù)(例如弦蹂,上面的createUser突變示例中的name)肩碟。
  • context:上下文,每個解析器都可以寫入和讀取的解析器鏈(基本上是解析器交流和共享信息的方法)的對象凸椿。
  • info:查詢或變異的AST表示削祈。您可以在這篇文章中了解更多信息:Demystifying the info Argument in GraphQL Resolvers.

以下是我們?nèi)绾螌崿F(xiàn)上述模式定義的解析器的一種可能方式(實現(xiàn)假定有一些全局對象數(shù)據(jù)庫提供了與數(shù)據(jù)庫的接口):

const Query = {
  users: (parent, args, context, info) => {
    return db.users()
  }
}

const Mutation = {
  createUser: (parent, args, context, info) => {
    return db.createUser(args.name)
  }
}

const User = {
  id: (parent, args, context, info) => parent.id,
  name: (parent, args, context, info) => parent.name,
}

上面的示例schema定義恰好具有四個字段。此解析器實現(xiàn)提供了四個相應(yīng)的解析器功能脑漫。請注意髓抑,User類型的解析器實際上可以省略,因為它們的實現(xiàn)是微不足道的优幸,并且由GraphQL執(zhí)行引擎推斷吨拍。

Prisma如何幫助開發(fā)GraphQL服務(wù)

構(gòu)建GraphQL服務(wù)的難點在于實現(xiàn)解析器(resolvers)

如上所見,實現(xiàn)GraphQL服務(wù)器的主要開發(fā)任務(wù)圍繞著定義schema并實現(xiàn)相應(yīng)的解析器(resolver)功能网杆。這也被稱為schema驅(qū)動開發(fā)(schema-driven development羹饰,SDD)。

當(dāng)實現(xiàn)解析器功能時碳却,您需要選擇某種數(shù)據(jù)源严里,為查詢響應(yīng)部分時獲取的數(shù)據(jù)。這個數(shù)據(jù)源可以是任何東西 - 它可能是一個數(shù)據(jù)庫(SQL或NoSQL)追城,一個REST API刹碾,一些第三方服務(wù)或任何類型的遺留系統(tǒng)。

上面的例子很簡單座柱,并假設(shè)全局數(shù)據(jù)庫對象的可用性為一些數(shù)據(jù)源提供了一個簡單的接口迷帜。實際上,您可能會遇到更復(fù)雜的場景色洞。特別是因為GraphQL查詢可以深度嵌套戏锹,將它們轉(zhuǎn)換為SQL(或其他數(shù)據(jù)庫API)非常麻煩并且容易出錯。

Prisma讓解析器變得簡單明了

使用Prisma時火诸,一般認為解析器只是將傳入查詢的執(zhí)行委托給底層的Prisma引擎锦针,而不是直接訪問數(shù)據(jù)庫。因此置蜀,大多數(shù)解析器實現(xiàn)將是簡單的單線程奈搜。將傳入查詢解釋為數(shù)據(jù)庫API的工作由Prisma完成

使用GraphQL bindings搞定這個事情盯荤,允許通過調(diào)用JavaScript中的專用函數(shù)(或任何其他用于后端開發(fā)的編程語言)與Prisma GraphQL API交互馋吗。如此,解析器實現(xiàn)變得與上面的模擬db示例一樣簡單秋秤。

GraphQL bindings - 更好的 ORM

綁定允許通過調(diào)用編程語言中的函數(shù)來發(fā)送查詢和突變

GraphQL bindings宏粤,在某種程度上與傳統(tǒng)的ORM有點像脚翘。他們都允許通過調(diào)用編程語言中的函數(shù)來與GraphQL API通訊,而不是構(gòu)建直接發(fā)送給API的原始查詢字符串绍哎。

像上面的createUser突變来农。無論何時您想將其發(fā)送到GraphQL API,您都需要像這樣拼出整個突變:

mutation {
  createUser(name: "Sarah") {
    id
  }
}

然后你將這個字符串放入HTTP POST請求的body并將它發(fā)送到API崇堰,這樣的缺點是查詢被表示為字符串备图。這抹殺了GraphQL的核心優(yōu)勢之一:強大的類型系統(tǒng)!基于字符串的方法完全沒有發(fā)揮強類型API的優(yōu)勢赶袄。

GraphQL bindings通過允許您調(diào)用專用函數(shù)來向API發(fā)送查詢和突變揽涮,而不是通過手動構(gòu)建字符串并通過HTTP將其發(fā)送到服務(wù)端。這些函數(shù)以您的GraphQL schema的根字段命名饿肺。

通過綁定蒋困,上面的createUser突變可以通過調(diào)用相同名稱的函數(shù)發(fā)送到服務(wù)端:

binding.mutation.createUser({ name: "Sarah" }, '{ id }')

同樣,你可以將上面的users查詢轉(zhuǎn)換為函數(shù)調(diào)用:

binding.query.users({}, '{ id name }')

如你所見敬辣,這些函數(shù)調(diào)用中的第一個參數(shù)是一個攜帶查詢(query)/突變(mutation)參數(shù)(args)的對象雪标,第二個參數(shù)是決定哪些數(shù)據(jù)應(yīng)該包含在響應(yīng)中的選擇集(selection set)。

調(diào)用這些方法時溉跃,引擎中的binding實例負責(zé)將操作轉(zhuǎn)換為GraphQL查詢村刨,并將查詢發(fā)送到服務(wù)端,并將響應(yīng)作為編程語言中的對象返回撰茎。

靜態(tài)與動態(tài)綁定(Static vs Dynamic Bindings)

綁定可以使用兩種風(fēng)格:靜態(tài)(Static)和動態(tài)(Dynamic)嵌牺。

靜態(tài)綁定(Static bindings )用于與來自靜態(tài)和強類型編程語言(如TypeScript或Scala)的GraphQL API進行交互時,在編譯時需要知道所有表達式的類型龄糊。在這種情況下逆粹,綁定函數(shù)在構(gòu)建時生成(使用代碼生成)。因此炫惩,這些綁定函數(shù)的所有調(diào)用都可以通過編譯器進行驗證僻弹,并且拼寫錯誤以及結(jié)構(gòu)錯誤(如錯誤類型的傳遞參數(shù))在編譯時被捕獲。

另一個優(yōu)勢是您的編輯器現(xiàn)在可以幫助您創(chuàng)建API請求他嚷,例如自動完成可用的操作和查詢參數(shù)蹋绽!這樣就改變了后端開發(fā)游戲的玩法,并將開發(fā)者體驗提升到一個新的水平筋蓖。沒有SQL字符串或其他脆弱的數(shù)據(jù)庫API - 幸虧有了Prisma綁定使你可以用強類型層與數(shù)據(jù)庫進行交互卸耘!

動態(tài)綁定(Dynamic bindings )通常用于動態(tài)編程語言(如JavaScript)。它們不需要額外的構(gòu)建步驟(靜態(tài)綁定就是如此)扭勉。綁定實例上的方法調(diào)用僅在運行時轉(zhuǎn)換為GraphQL查詢鹊奖。這仍然提供了使用簡潔和簡單的綁定語法的主要好處。使用適當(dāng)?shù)臉?gòu)建工具仍然可以實現(xiàn)構(gòu)建時錯誤檢查和自動完成等優(yōu)勢涂炎。

架構(gòu)入門:兩個GraphQL API層

在使用Prisma構(gòu)建GraphQL服務(wù)器時忠聚,您需要處理兩個GraphQL API:

  • database layer:由Prisma負責(zé)的數(shù)據(jù)庫層
  • application layer:應(yīng)用層負責(zé)與寫入或讀取數(shù)據(jù)庫數(shù)據(jù)無關(guān)的任何功能(如業(yè)務(wù)邏輯,身份驗證和權(quán)限唱捣,第三方集成等)两蟀。

數(shù)據(jù)庫層完全通過prisma.yml進行配置,并使用Prisma CLI進行管理震缭。應(yīng)用層是您正在用自己喜歡的編程語言實現(xiàn)的GraphQL服務(wù)赂毯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拣宰,隨后出現(xiàn)的幾起案子党涕,更是在濱河造成了極大的恐慌,老刑警劉巖巡社,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膛堤,死亡現(xiàn)場離奇詭異,居然都是意外死亡晌该,警方通過查閱死者的電腦和手機肥荔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朝群,“玉大人燕耿,你說我怎么就攤上這事〗郑” “怎么了誉帅?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長右莱。 經(jīng)常有香客問我堵第,道長,這世上最難降的妖魔是什么隧出? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任踏志,我火速辦了婚禮,結(jié)果婚禮上胀瞪,老公的妹妹穿的比我還像新娘针余。我一直安慰自己,他們只是感情好凄诞,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布圆雁。 她就那樣靜靜地躺著,像睡著了一般帆谍。 火紅的嫁衣襯著肌膚如雪伪朽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天汛蝙,我揣著相機與錄音烈涮,去河邊找鬼朴肺。 笑死,一個胖子當(dāng)著我的面吹牛坚洽,可吹牛的內(nèi)容都是我干的戈稿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼讶舰,長吁一口氣:“原來是場噩夢啊……” “哼鞍盗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跳昼,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤般甲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹅颊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敷存,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年挪略,在試婚紗的時候發(fā)現(xiàn)自己被綠了历帚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡杠娱,死狀恐怖挽牢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情摊求,我是刑警寧澤禽拔,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站室叉,受9級特大地震影響睹栖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茧痕,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一野来、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧踪旷,春花似錦曼氛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至气破,卻和暖如春聊浅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工低匙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留旷痕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓努咐,卻偏偏與公主長得像苦蒿,于是被迫代替她去往敵國和親殴胧。 傳聞我的和親對象是個殘疾皇子渗稍,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。 當(dāng)搞定了GraphQL服務(wù)端開發(fā)团滥,且經(jīng)過充分測試竿屹,那么接著需要...
    guog閱讀 2,650評論 0 1
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。 本教程學(xué)習(xí)如何使用Prisma對數(shù)據(jù)庫生成GraphQL AP...
    guog閱讀 7,257評論 2 3
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列灸姊。 本文介紹如何使用typescript開發(fā)prisma服務(wù)拱燃。將使...
    guog閱讀 2,926評論 0 2
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。 在本教程中力惯,您將學(xué)習(xí)如何在使用Prisma和graphql-y...
    guog閱讀 1,220評論 1 0
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列碗誉。 要理解Prisma是什么以及它是如何工作的,至關(guān)重要的是你對G...
    guog閱讀 7,820評論 0 1