GraphQL 漸進學習 05-graphql-resolvers-union-聯合的使用
目標
程式碼
步驟
1. 準備測試靜態資料
const notices = [{id: 1, content: `這是 notice`, noticeTime: 1524710641}]
const reminds = [{id: 1, content: `這是 remind`, endTime: 1524710641}]
2. 編寫 typeDefs
const typeDefs = `
scalar Date
interface Message {
content: String
}
type Notice implements Message {
content: String
noticeTime: Date
}
type Remind implements Message {
content: String
endTime: Date
}
"""
聯合型別 通知 & 提醒
"""
union MessageResult = Notice | Remind
type Query {
searchUnion (text: String!): MessageResult!
}
`
-
MessageResult
聯合物件
-
searchUnion
供客戶端查詢使用方法
3. 編寫 resolvers
const resolvers = {
Query: {
searchUnion: (_, {text}) => {
if (text === `notice`) {
return notices[0]
} else {
return reminds[0]
}
}
},
MessageResult: {
__resolveType(obj, context, info){
console.log(obj, context, info)
if(obj.noticeTime){
return `Notice`
}
if(obj.endTime){
return `Remind`
}
return null
}
},
Date: new GraphQLScalarType({
name: `Date`,
description: `Date custom scalar type`,
parseValue(value) {
return new Date(value) // value from the client
},
serialize(value) {
// return new Date(value).getTime()
return new Date(value) // value sent to the client
},
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
return parseInt(ast.value, 10) // ast value is always in string format
}
return null
}
})
}
-
searchUnion
搜尋方法實現,直接返回一條通知或提醒
-
__resolveType
返回型別定義
-
if(obj.noticeTime){
如果含有 noticeTime 欄位判定是通知
4. 合併 Schema
const schema = makeExecutableSchema({
typeDefs,
resolvers
})
測試
1. 請求 searchUnion
方法
# 請求 query
query do($text: String!) {
searchUnion(text: $text) {
... on Notice {
content
noticeTime
}
... on Remind {
content
endTime
}
}
}
# 變數 variables
{
"text": "notice"
}
# 輸出
{
"data": {
"searchInterface": {
"content": "這是 notice",
"endTime": "1970-01-18T15:31:50.641Z"
}
}
}
- 我們可以試著把
content
欄位提出,發現查詢報錯,這個和 interface
還是有區別的
# 錯誤
{
"errors": [
{
"message": "Cannot query field "content" on type "MessageResult". Did you mean to use an inline fragment on "Message", "Notice", or "Remind"?",
"locations": [
{
"line": 3,
"column": 5
}
]
}
]
}
詳細請移步 04-graphql-resolvers-interfaces-介面的使用
2. 列印 __resolveType(obj, context, info)
引數
# obj
{ id: 1, content: `這是 notice`, noticeTime: 1524710641 }
# context
{}
# info
{ fieldName: `searchUnion`,
fieldNodes:
[ { kind: `Field`,
alias: undefined,
name: [Object],
arguments: [Array],
directives: [],
selectionSet: [Object],
loc: [Object] } ],
returnType: MessageResult!,
parentType: Query,
path: { prev: undefined, key: `searchUnion` },
schema:
GraphQLSchema {
__allowedLegacyNames: undefined,
_queryType: Query,
_mutationType: Mutation,
_subscriptionType: null,
_directives: [ [Object], [Object], [Object] ],
astNode: undefined,
_typeMap:
{ Query: Query,
Post: Post,
Int: Int,
String: String,
Author: Author,
Country: Country,
Message: Message,
MessageResult: MessageResult,
Notice: Notice,
Date: Date,
Remind: Remind,
Mutation: Mutation,
AuthorInput: AuthorInput,
__Schema: __Schema,
__Type: __Type,
__TypeKind: __TypeKind,
Boolean: Boolean,
__Field: __Field,
__InputValue: __InputValue,
__EnumValue: __EnumValue,
__Directive: __Directive,
__DirectiveLocation: __DirectiveLocation },
_implementations: { Message: [Array] },
__validationErrors: [],
_possibleTypeMap: { MessageResult: [Object] } },
fragments: {},
rootValue: undefined,
operation:
{ kind: `OperationDefinition`,
operation: `query`,
name: { kind: `Name`, value: `do`, loc: [Object] },
variableDefinitions: [ [Object] ],
directives: [],
selectionSet: { kind: `SelectionSet`, selections: [Array], loc: [Object] },
loc: { start: 0, end: 173 } },
variableValues: { text: `notice` } }
參考