Источник: Nuances of Programming
GraphQL — это язык запросов к API-интерфейсам. Он отображает предоставляемые сервером данные, чтобы клиент смог выбрать именно то, что ему нужно.
Помимо этого, с помощью GraphQL можно получить несколько ресурсов сервера одним вызовом, а не выполнять множество вызовов REST API.
Однако трудно оценить преимущества GraphQL, не попробовав его в действии. Поэтому рассмотрим использование GraphQL на практических примерах.
Мы будем использовать GraphQL вместе с NodeJS.
Предварительные требования
Перед началом работы установите NodeJS.
Как использовать GraphQL с NodeJs
GraphQL используется с различными ЯП. Рассмотрим пример использования GraphQL с JavaScript, используя NodeJS.
Создайте папку под названием graphql-with-nodejs. Запустите команду npm init в папке проекта, чтобы создать проект NodeJS. Команда представлена ниже:
cd graphql-with-nodejs npm init
Установка зависимостей
Установите Express с помощью следующей команды:
npm install express
Установите GraphQL с помощью следующей команды. Устанавливаем GraphQL и GraphQL для Express.
npm install express-graphql graphql
Код NodeJS
Создайте файл server.js внутри проекта и скопируйте в него следующий код:
Приведенный код содержит одну конечную точку (endpoint) HTTP GET с названием /hello.
Endpoint создается с помощью Express.
Теперь изменим этот код, чтобы запустить GraphQL.
Запуск GraphQL в коде
У GraphQL будет один URL endpoint с именем /graphql, который обрабатывает все запросы.
Скопируйте следующий код в server.js:
Теперь пройдемся по коду.
С помощью graphqlHTTP сервер GraphQL устанавливается в URL-адрес /graphql. Он обрабатывает поступающие запросы.
Процесс установки представлен в следующих строчках кода:
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true,
}));
Теперь изучим параметры внутри graphqlHTTP.
graphiql
graphiql — это веб-интерфейс, с помощью которого тестируются endpoints GraphQL. Устанавливаем значение true, чтобы было легче тестировать различные endpoints GraphQL.
schema
У GraphQL есть лишь один endpoint /graphql. Он может обладать несколькими endpoints, выполняющими различные действия. Они указаны в схеме.
Схема выполняет следующие действия:
- Указывает различные endpoints
- Определяет поля ввода и вывода для endpoint
- Определяет действие, которое должно быть выполнено при достижении endpoint и так далее.
Схема определяется в коде следующим образом:
const schema = new GraphQLSchema({ query: queryType });
Схема может содержать как запрос, так и типы мутации. Мы будем рассматривать только тип query.
query
По схеме видно, что query установлен в queryType.
Импортируем queryType из файла query.js с помощью следующей команды:
const {queryType} = require('./query.js');
query.js — это пользовательский файл.
query — это место, куда мы определяем endpoints типа read-only в схеме.
Создайте файл с названием query.js в проекте и скопируйте в него следующий код.
query Explained
queryType создан как GraphQLObjectType с названием Query.
fields — это место, куда мы определяем endpoints.
Здесь мы добавляем один endpoint под названием hello.
hello относится к типу GraphQLString, т.е возвращает тип String. В схеме GraphQL используется тип GraphQLString вместо String. Прямое использованиеString не работает.
Функция resolve указывает действие, которое должно быть выполнено при достижении endpoint. В данном случае возвращается строка “Hello World”.
Теперь экспортируем querytype с помощью exports.queryType = queryType, чтобы убедиться, что он может быть импортирован в server.js.
Запуск приложения
Запустите приложение, используя следующую команду:
node server.js
Приложение работает на localhost:5000/graphql.
Можно протестировать приложение, перейдя на localhost:5000/graphql.
Этот URL-адрес управляет веб-интерфейсом Graphiql, как указано на скриншоте ниже.
Входные данные указаны слева, а выходные — справа.
Вводим следующее:
Поздравляем😃
Вы создали свой первый endpoint GraphQL.
Добавление нескольких endpoints
Создадим еще две конечных точки (endpoints):
- movie: этот endpoint возвращает фильм, получивший ID фильма
- director: этот endpoint возвращает режиссера, получившего ID режиссера. Он также вернет все фильмы, снятые этим режиссером.
Добавление данных
Обычно приложение прочитывает данные из Базы данных. Но в этом примере, мы будем хардкодить данные в самом коде.
Создайте файл data.js и скопируйте в него следующий код.
В этом файле содержатся данные о фильмах и режиссерах. Используем данные из этих файлов для наших endpoints.
Добавление endpoint movie в запрос
Новые endpoints будут добавлены к queryType в файл query.js.
Код для endpoint movie представлен ниже:
Тип возвращаемого значения этого endpoint — movieType, который скоро будет определен.
С помощью параметра args указываются входные данные для endpoint movie. Входные данные для этого endpoint — id типа GraphQLInt.
Функция resolve возвращает фильм, соответствующий id, из списка фильмов. Функция find из библиотеки lodash используется для поиска элемента в списке.
Полный код для query.js представлен ниже:
Из приведенного кода видно, что movieType действительно определен в types.js.
Добавление пользовательского типа movieType
Создайте файл с названием types.js.
Добавьте следующий код в types.js:
movieType создан в качестве GraphQLObjectType.
Он обладает четырьмя полями: id, name, year и directorId. Типы для каждого поля устанавливаются в процессе их добавления.
Эти поля поступают непосредственно из данных. В данном случае, из списка movies.
Добавление запроса и типа для endpoint director
В query.js endpoint director добавляется следующим образом:
directorType добавляется следующим образом в types.js:
Минуточку. directorType немного отличается от movieType. В чем причина?
Почему функция resolve находится внутри directorType? Ранее функции resolve присутствовали только в query…
Особенности directorType
При вызове endpoint director необходимо возвратить подробную информацию о режиссере, а также всего его фильмы.
Первые три поля id, name, age в directorType исходят непосредственно из данных (список directors).
Четвертое поле movies должно содержать список фильмов этого режиссера.
По этой причине, следует упомянуть, что тип поля movies относится к GraphQLList от movieType (Список фильмов).
Однако каким образом найти все фильмы, снятие этим режиссером?
Для этого в поле movies есть функция resolve. Входные данные для функции resolve — source и args.
source будет содержать подробную информацию о родительском объекте.
Допустим, поля для режиссера id =1, name = “Random” и age = 20. Затем source.id =1, source.name = “Random” и source.age = 20
Таким образом, в этом примере функция resolve найдет все фильмы, в которых directorId соответствует Id запрашиваемого режиссера.
Тестирование приложения
Протестируем приложение для различных сценариев.
Запустите приложение с помощью node server.js.
Зайдите на localhost:5000/graphql и введите следующие данные.
movie
Входные данные:
Приведенный пример показывает, что клиент может запросить именно то, что ему нужно, а GraphQL предоставит необходимые параметры. Сервер выдает только запрошенное поле name.
В movie(id: 1) id находится во входном параметре. Мы запросили у сервера фильм с id=1.
Входные данные:
В приведенном выше примерe сервер выдает запрашиваемые поля name, id и year.
director
Входные данные:
Приведенный пример показывает возможности GraphQL. Нам нужен режиссер с id=1 и все его фильмы. Поля director и movie являются произвольными, поэтому клиент может запросить именно то, что ему нужно.
Аналогичным образом можно запрашивать другие поля и типы. К примеру, можно сделать запрос: Поиск режиссера с id=1 и всех его фильмов. Поиск актеров для каждого фильма, а для каждого актера 5 его лучших фильмов и так далее. Для этого запроса необходимо указать отношения между типами и тогда можно будет запросить любое необходимое отношение.
Поздравляем 😃
Теперь вы знакомы с базовыми концепциями GraphQL.
Чтобы узнать больше, можете посмотреть официальную документацию.
Читайте нас в телеграмме и vk
Перевод статьи Aditya Sridhar: An introduction to GraphQL: how it works and how to use it