GraphQL
GraphQL按照官方的說(shuō)法它是一門(mén)聲明式的查詢語(yǔ)言段只,實(shí)際上它是領(lǐng)域特定查詢語(yǔ) DSQL趣惠,它通過(guò)定義的schema系統(tǒng)將復(fù)雜的邏輯拆分成細(xì)粒度的數(shù)據(jù)結(jié)構(gòu)狸棍,來(lái)讓前端應(yīng)用的開(kāi)發(fā)者能夠通過(guò)GraphQL提供的類型查詢系統(tǒng),自由定制請(qǐng)求數(shù)據(jù)的能力味悄。
GraphQL與RESTful
目前大多數(shù)應(yīng)用的API采用的都是流行的RESTful API草戈,但是對(duì)于很多需求變更頻繁的,數(shù)據(jù)查詢顆粒的小的應(yīng)用來(lái)說(shuō)侍瑟,使用RESTful的API總是在不斷的迭代唐片,不斷的更新版本丙猬。這會(huì)導(dǎo)致應(yīng)用的API系統(tǒng)過(guò)于復(fù)雜,而且通常最后又大量冗余的API進(jìn)而變動(dòng)難以維護(hù)费韭。
“The REST interface is designed to be efficient for large-grain hypermedia data transfer…” - Dr Roy T Fielding, Author of REST
其實(shí)REST本身更適合數(shù)據(jù)力度大茧球,需求變更不頻繁的應(yīng)用場(chǎng)景,而在細(xì)粒度的應(yīng)用場(chǎng)景下的解決方案揽思,在Facebook的復(fù)雜系統(tǒng)中應(yīng)運(yùn)而生袜腥,GraphQL被用于解決細(xì)粒度的API問(wèn)題已經(jīng)3年多了,處理了260多億次的請(qǐng)求钉汗,這注意證明它在真實(shí)的場(chǎng)景下是經(jīng)得起考驗(yàn)的羹令。
整個(gè)GraphQL的核心就是一個(gè)類型定義系統(tǒng),通過(guò)定義各種可能的查詢類型和所有的返回?cái)?shù)據(jù)的類型损痰,來(lái)構(gòu)建一個(gè)查詢系統(tǒng)福侈,讓客戶端通過(guò)統(tǒng)一的查詢語(yǔ)言,來(lái)對(duì)系統(tǒng)中的類型進(jìn)行匹配卢未,并最終返回肪凛,相匹配的數(shù)據(jù)。
GraphQL 由以下組件構(gòu)成:
- 類型系統(tǒng)(Type System)
- 查詢語(yǔ)言(Query Language)
- 執(zhí)行語(yǔ)義(Execution Semantics)
- 靜態(tài)驗(yàn)證(Static Validation)
- 類型檢查(Type Introspection)
類型
GraphQL中類型系統(tǒng)是最重要的組成部分之一辽社,其中提供的類型分為兩種伟墙,一種是標(biāo)量類型,用于表示最細(xì)粒度的類型滴铅,這些類型基本可以和JavaScript戳葵,Ruby及其他通用編程語(yǔ)言對(duì)應(yīng)上。
標(biāo)量類型:
- Int : 整數(shù)汉匙,對(duì)應(yīng) JavaScript 的Number
- Float :浮點(diǎn)數(shù)拱烁,對(duì)應(yīng) JavaScript 的 Number
- Boolean:布爾值,對(duì)應(yīng) JavaScript 的 Boolean
- String : 字符串噩翠,對(duì)應(yīng) JavaScript 的 String
- ID : D 值戏自,是一個(gè)序列化后值唯一的字符串,可以視作對(duì)應(yīng) ES 2015 新增的 Symbol
其他的高級(jí)類型:
- Object : 對(duì)象類型 伤锚,用于表示GraphQL返回類型樹(shù)的中間層級(jí)擅笔,標(biāo)量類型表示的都是葉子節(jié)點(diǎn),在GraphQL基本上所以的類型都是Object類型屯援,它包含有一個(gè)name字段來(lái)描述定義的類型和fields字段描述該類型的完整數(shù)據(jù)結(jié)構(gòu)猛们。
var AddressType = new GraphQLObjectType({
name: 'Address',
fields: {
street: { type: GraphQLString },
number: { type: GraphQLInt },
formatted: {
type: GraphQLString,
resolve(obj) {
return obj.number + ' ' + obj.street
}
}
}
});
- Interface : 接口類型 用于描述多個(gè)類型中通用的字段
var EntityType = new GraphQLInterfaceType({
name: 'Entity',
fields: {
name: { type: GraphQLString }
}
});
- Union : 聯(lián)合 它有點(diǎn)像可選類型,用于表示這一個(gè)字段可能是一個(gè)類型集合下的某一種類型玄呛。
var PetType = new GraphQLUnionType({
name: 'Pet',
types: [DogType, CatType],
resolveType(value) {
if (value instanceof Dog) {
return DogType;
}
if (value instanceof Cat) {
return CatType;
}
}
});
- Enum :枚舉類型
var RGBType = new GraphQLEnumType({
name: 'RGB',
values: {
RED: { value: 0 },
GREEN: { value: 1 },
BLUE: { value: 2 }
}
});
- List : 列表類型
var PersonType = new GraphQLObjectType({
name: 'Person',
fields: () => ({
parents: { type: new GraphQLList(Person) },
children: { type: new GraphQLList(Person) },
})
});
- Non-Null : 不為空類型阅懦,用于表示返回的字段不為空,如果為空就會(huì)發(fā)生異常徘铝,可用于數(shù)據(jù)庫(kù)的主鍵耳胎。
var RowType = new GraphQLObjectType({
name: 'Row',
fields: () => ({
id: { type: new GraphQLNonNull(GraphQLString) }
})
});
查詢
GraphQL的客戶端惯吕,是通過(guò)一個(gè)查詢字符串通過(guò),GraphQL服務(wù)可以解析驗(yàn)證并執(zhí)行這樣的查詢請(qǐng)求字符串怕午,一個(gè)查詢字符串有兩部分組成:操作(Operation)和片段(Fragments) 一個(gè) query 可以包含多個(gè)操作和片段废登。只有包含操作的 query 才會(huì)被 GraphQL 服務(wù)執(zhí)行。但是不包含操作郁惜,只有片段的 query 也會(huì)被 GraphQL 服務(wù)解析驗(yàn)證堡距,這樣一份片段就可以在多個(gè) query 文檔內(nèi)使用。
GraphQL 規(guī)范支持兩種操作:
let schema = new GraphQLSchema({ query: UserType mutation: UpdateAgeType});
- query:僅獲取數(shù)據(jù)(fetch)的只讀請(qǐng)求
query {
user(id: 3500401) {
id,
name,
age
}
}
- mutation:獲取數(shù)據(jù)后還有寫(xiě)操作的請(qǐng)求
mutation {
updateAage
}
其中GraphQL對(duì)數(shù)據(jù)的修改稱為mutation 兆蕉,它在GraphQL的查詢系統(tǒng)中是按照順序序列化執(zhí)行的羽戒。
查詢請(qǐng)求模型:
總結(jié)
GraphQL在技術(shù)上提供了區(qū)別于REST的解決方案,很好的解決了數(shù)據(jù)細(xì)粒度頻繁變更的問(wèn)題虎韵,使得數(shù)據(jù)和接口得到了解綁易稠,在生態(tài)圈方便面,現(xiàn)已經(jīng)有很多語(yǔ)言的GraphQL實(shí)現(xiàn)(Python 包蓝、Ruby 等)可以參見(jiàn) GraphQL Awesome list驶社。在應(yīng)用方面雖然是2015年才被Facebook公布并且開(kāi)源的,但是它已經(jīng)在Facebook的應(yīng)用系統(tǒng)中工作了快四年之久测萎。而且現(xiàn)在不少國(guó)內(nèi)的團(tuán)隊(duì)(比如淘寶)也已經(jīng)在使用GraphQL構(gòu)建應(yīng)用系統(tǒng)的API亡电,這些都足以證明這項(xiàng)技術(shù)的市場(chǎng)和潛力了。