Функция buildSchema
берет схему в SDL (язык определения схемы) и возвращает объект GraphQLSchema
.При наличии двух идентичных схем, генерируемых каждым методом, производительность во время выполнения будет одинаковой.Время запуска для сервера, использующего buildSchema
, будет медленнее, так как при разборе SDL добавляется дополнительный шаг, который в противном случае не существовал бы - будет ли заметная разница, я не могу сказать однозначно.
Использование buildSchema
, как правило, нецелесообразно, так как оно серьезно ограничивает функциональность вашей схемы.
Схема, созданная с использованием buildSchema
:
- Невозможно указать функции разрешения для отдельных полей
- Невозможно указать свойства
resolveType
или isTypeOf
для типов, что делает невозможным использование Unions
и Interfaces
- Невозможно использовать пользовательские скаляры
Элемент # 1 не может быть подчеркнут достаточно - buildSchema
не позволяет вам указать функцию распознавателя для любого поля в вашей схеме.Это включает в себя поля для типов Query
и Mutation
.Примеры, использующие buildSchema
, решают эту проблему, полагаясь на поведение распознавателя по умолчанию в GraphQL и передавая значение root
.
По умолчанию, если в поле не указана функция resolve
, GraphQL проверит родительское значение (возвращаемое распознавателем родительского поля) и (при условии, что это объект) попытается найти свойствона том родительском значении, которое соответствует имени поля.Если он находит совпадение, он разрешает поле к этому значению.Если совпадение является функцией, она сначала вызывает эту функцию, а затем преобразуется в значение, возвращаемое функцией.
В приведенном выше примере поле hello
в первой схеме не имеет преобразователя,GraphQL просматривает родительское значение, которое для полей корневого уровня является значением root , которое передается. Корневое значение имеет поле с именем hello
, и это функция, поэтомуон вызывает функцию, а затем преобразуется в значение, возвращаемое функцией.Вы можете добиться того же эффекта, просто сделав свойство hello
String вместо функции.
Учитывая вышеизложенное, два примера в вопросе на самом деле не одинаковы,Скорее, нам пришлось бы изменить вторую схему, как это, чтобы она была эквивалентной:
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
hello: {
type: GraphQLString,
}
})
})
});
const root = { hello: () => 'Hello world!' };
graphql(schema, '{ hello }', root).then((response) => {
console.log(response);
});
Хотя передача резолвера через корень - это хитрый трюк, опять же, он работает только для полей корневого уровня (например,поля типов Query
, Mutation
или Subscription
).Если вы хотите предоставить распознаватель для поля другого типа, сделать это невозможно, используя buildSchema
.
Итог: не используйте buildSchema
.
Но я хотел использовать SDL!
И вы все еще можете! Но ... не делайте этого с помощью vanilla GraphQL.js.Вместо этого, если вы хотите использовать SDL для генерации вашей схемы, вам следует либо использовать graphql-tools
'makeExecutableSchema
, либо использовать более полное решение, такое как apollo-server
, которое использует makeExecutableSchema
под капотом.makeExecutableSchema
позволяет вам определять схему с использованием SDL, а также предоставляет отдельный объект resolvers
.Таким образом, вы можете сделать:
const typeDefs = `
type Query {
hello: String
}
`
const resolvers = {
Query: {
hello: () => 'Hello!',
},
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
Разница в том, что, в отличие от buildSchema
, вы также можете предоставлять преобразователи для других типов и даже предоставлять resolveType
свойства для ваших интерфейсов или объединений.
const resolvers = {
Query: {
animals: () => getAnimalsFromDB(),
}
Animal: {
__resolveType: (obj) => obj.constructor.name
},
Cat: {
owner: (cat) => getOwnerFromDB(cat.ownerId),
}
}
Используя makeExecutableSchema
, вы также можете реализовывать собственные скаляры и директивы схемы, легко настраивать различные правила проверки схемы и даже разрешать реализующим типам наследовать средства распознавания от их интерфейсов.Хотя очень важно понять основы GraphQL.js и как сгенерировать базовую схему с помощью конструктора GraphQLSchema
, makeExecutableSchema
является более полным и гибким решением, которое должно быть выбрано для большинства проектов. Подробнее см. В документах .
ОБНОВЛЕНИЕ
Если вы склонны использовать buildSchema
, на самом деле можно обойти невозможность предоставления преобразователей для некорневых типов с помощью классов ES6.Проверьте этот пример схемы .Это не устраняет все другие ограничения buildSchema
, но делает его более приемлемым.