一個(gè)GraphQL查詢在被驗(yàn)證后,GraphQL服務(wù)器會(huì)將之執(zhí)行。
- 一個(gè)例子
type Query {
human(id: ID!): Human
}
type Human {
name: String
appearsIn: [Episode]
starships: [Starship]
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Starship {
name: String
}
{
human(id: 1002) {
name
appearsIn
starships {
name
}
}
}
{
"data": {
"human": {
"name": "Han Solo",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
],
"starships": [
{
"name": "Millenium Falcon"
},
{
"name": "Imperial shuttle"
}
]
}
}
}
- GraphQL工作原理:GraphQL查詢中的每個(gè)字段視為返回子類型的父類型函數(shù)或方法,每個(gè)類型的每個(gè)字段都有一個(gè)resolver函數(shù)支持,該函數(shù)由GraphQL服務(wù)器開發(fā)人員提供,當(dāng)一個(gè)字段被執(zhí)行時(shí),相應(yīng)的resolver被調(diào)用產(chǎn)生下一個(gè)值。如果字段產(chǎn)生標(biāo)量值,則執(zhí)行完成,如果產(chǎn)生對象,則該查詢將繼續(xù)執(zhí)行該對象對應(yīng)的解析器,知道返回標(biāo)量值。
根字段 & 解析器
GraphQL服務(wù)端應(yīng)用頂層,必有一個(gè)類型代表所有進(jìn)入GraphQL API可能的入口,成為
Root
/Query
類型上述例子中查詢了
human
字段,接收一個(gè)參數(shù)id,服務(wù)端的解析器可能實(shí)現(xiàn)如下
Query: {
human(obj, args, context) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}
- 解析器函數(shù)接收3個(gè)參數(shù):
- obj上一級(jí)對象,如果字段輸入根節(jié)點(diǎn)查詢,通常不會(huì)被使用
- args可以提供在GraphQL查詢中傳入的參數(shù)
- context被提供給所有解析器,并且持有重要的上下文信息,比如當(dāng)前登入的用戶、數(shù)據(jù)庫訪問對象
異步解析器
human(obj, args, context) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
- context提供了數(shù)據(jù)庫訪問對象,調(diào)用數(shù)據(jù)庫訪問方法,返回一個(gè)Promise,在回調(diào)中,實(shí)例化一個(gè)新的Human對象
- 在執(zhí)行期間,如果異步操作沒有完成,則GraphQL會(huì)一直等待下去,所以需要關(guān)注異步處理的優(yōu)化
不重要的解析器
對于產(chǎn)生的Human,GraphQL會(huì)繼續(xù)遞歸執(zhí)行下去
Human: {
name(obj, args, context) {
return obj.name
}
}
- name字段,返回上層回調(diào)產(chǎn)生的new Human對象上的name屬性