GraphQL
В последние годы он упоминается все чаще и чаще, и упоминался во фронтенд-ветках нескольких технологических конференций, в которых я недавно участвовал. В таких вещах все еще есть какая-то загадка, что нелегко понять, что это такое, просто взглянув на название. Итак, собираемся узнатьGraphQL
что именно это такое.
Что такое GraphQL?
первый,GraphQL
Из Facebook, если вы, как и я, вообще его не знаете и не знаете, что он делает, то вы, должно быть, слышали о другом, называемомStructured QL
с вещами. ЧТО?По сути, это SQL.
- гм, и
SQL
Такой же,GraphQL
это язык запросов (Query Language) - то же самое и
SQL
То же самое,GraphQL
также является набором норм, напримерMySQL
даSQL
Тот же набор реализаций,Apollo
,Relay
...СлишкомGraphQL
Реализация спецификации - а также
SQL
разница в том,SQL
Источником данных GraphQL является база данных, а источником данных GraphQL могут быть различные REST API, различные сервисы/микросервисы или даже базы данных.
Вот изображение с официального сайта Apollo, иллюстрирующее положение GraphQL в архитектуре интернет-приложений.
несколько моментов времени
- Спецификация GraphQL была открыта в 2015 году.
- Операция «Подписки» была добавлена в спецификацию в 2017 году.
Так почему он называетсяGraphШерстяная ткань?
Graphсмысл картины, вGraphQL
В мире все представляет собой граф, а это значит, что вы можете смоделировать свою бизнес-модель в виде графа.
Графики — мощные инструменты для моделирования многих явлений реального мира, поскольку они напоминают наши естественные ментальные модели и словесные описания основных процессов.
Здесь задействована теория графов.Graph DatabaseТакие знания, если вам интересно, вы можете выучить определенную песню.
Таким образом, мы можем получить общее представление о GraphQL. Итак, давайте взглянем на GraphQL в целом.
Какую проблему решает для нас GraphQL?
Проще говоря, с точки зрения внешнего интерфейса во многих статьях упоминается, что для замены Restful API нужно быть немного более конкретным:
- Настройка полей API, использование полей по мере необходимости
- Агрегация API, получение всех данных одним запросом
- Серверной части больше не нужно поддерживать номер версии интерфейса.
- Полный механизм проверки типов, обеспечивающий более надежный интерфейс
- . . .
Прежде чем узнать, как достигаются вышеуказанные преимущества, давайте проведем простое изучение GraphQL.
Интерфейсное обучение GraphQL
Как фронтенд-разработчику, только с точки зрения фронтенда, чаще всего нам нужно заботиться только о двух операциях:
-
запрос: В GraphQL это ключевое слово относится к типу схемы (что можно понимать как протокол), что означает, что то, что вы хотите выполнить, является действием запроса, то есть запросом в CRUD.
-
мутация: означает, что действие, которое вы хотите выполнить, это добавление, удаление и изменение
query
а такжеmutation
в совокупности именуемыеschema. На самом деле есть еще одинsubscriptionsВ 2017 году его добавили в спецификацию (spec), что позволило нам проще реализовать функцию push.
Здесь мы берем два сценария внутренней платформы обмена в качестве примера, чтобы показать, как использовать эти две операции.
операция запроса
Прежде всего, в самом простом сценарии домашняя страница платформы обмена должна вызывать интерфейс для получения всех списков обмена Текущий метод вызова этого интерфейса:
GET /api/share/allShares
вернуть
{
"shares": [
{
"shareId": 1238272,
"title": "分享一下Vue3.0",
"desc": "Vue3.0就要发布了,带来了哪些新功能呢?",
"where": "6F-19会议室",
"startTime": 1548842400
},
{
"shareId": 1238272,
"title": "用flutter写app页面是一种什么样的体验",
"desc": "用跨平台框架flutter来写app页面的初体验",
"where": "6F-17会议室",
"startTime": 1548842400
},
{
"shareId": 1238272,
"title": "Cordova原理",
"desc": "一起来了解一下Cordova",
"where": "6F-19会议室",
"startTime": 1548842400
}
]
}
Так что вместо GraphQL мы можем написать
query {
shares {
title
desc
where
startTime
}
}
Хм? Обнаружено, что поле отсутствует.Если мы хотим перейти на страницу сведений, нам нужно знать общий идентификатор и изменить его.
# 给一个查询起一个名字是一个好习惯
query findAllShares {
shares {
# 为id起了一个别名,叫shareId
shareId: id
title
desc
where
startTime
}
}
На этом базовая операция запроса завершена.
нумерация страниц
Обычно, если объем данных списка относительно велик, мы будем использовать пейджинг для получения данных, а не получать все данные за один раз, по-прежнему берем в качестве примера список общего доступа, если используется традиционный метод вызова интерфейса, он обычно необходимо вызвать интерфейс следующим образом:
GET /api/share/allShares?star=0&limit=10
вернуть
{
"allShares": {
"totalCount": 3,
"shares": [
{
"shareId": 1238272,
"title": "分享一下Vue3.0",
"desc": "Vue3.0就要发布了,带来了哪些新功能呢?",
"where": "6F-19会议室",
"startTime": 1548842400
},
{
"shareId": 1238273,
"title": "用flutter写app页面是一种什么样的体验",
"desc": "用跨平台框架flutter来写app页面的初体验",
"where": "6F-17会议室",
"startTime": 1548842400
},
{
"shareId": 1238274,
"title": "Cordova原理",
"desc": "一起来了解一下Cordova",
"where": "6F-19会议室",
"startTime": 1548842400
}
]
}
}
Давайте продолжим трансформировать способ GraphQL, способ пейджинга:
# 分页方式
query findAllShares($start: Int!, $limit: Int = 10) {
allShares (start: $start, limit: $limit) {
totalCount
shares {
shareId: id
title
desc
where
startTime
}
}
}
GraphQL предоставляет полное решение для подкачки, вы можете обратиться кPagination
В следующей сцене, после получения всех списков общего доступа, вы можете перейти на страницу сведений. В настоящее время на странице сведений есть три основных интерфейса запроса: получить сведения об общем доступе, получить список общих комментариев и получить все списки общего доступа пользователя. Если это традиционный способ, нам нужно настроить три интерфейса:
// 获取分享的详情
GET /api/share/:shareId
// 分享详情返回
{
"shareDetail": {
"shareId": 1238274,
"title": "Cordova原理",
"desc": "一起来了解一下Cordova",
"where": "6F-19会议室",
"startTime": 1548842400,
"attchments": "",
"creatorId": 321,
"lastUpdateTime": 1548842400,
"logoUrl": "",
...
}
}
// 获取分享的评论列表
GET /api/share/comments/:shareId
// 分享评论列表返回
{
"commentInfo": {
"totalCount": 5,
"comments": [
{
"id": 1,
"content": "非常不错",
"userId": 213,
"commentTime": 1548842400,
},
{
"id": 2,
"content": "很好",
"userId": 214,
"commentTime": 1548842400,
},
{
"id": 3,
"content": "不错",
"userId": 216,
"commentTime": 1548842400,
},
{
"id": 4,
"content": "Very GOOD!",
"userId": 2313,
"commentTime": 1548842400,
}
]
}
}
// 分享的创建者的创建的全部分享列表
GET /api/share/shares/:creatorId
// 分享创建者的全部分享返回
{
"hisShares": [
{
"shareId": 1238272,
"title": "分享一下Vue3.0",
"desc": "Vue3.0就要发布了,带来了哪些新功能呢?",
"where": "6F-19会议室",
"startTime": 1548842400
},
{
"shareId": 1238273,
"title": "用flutter写app页面是一种什么样的体验",
"desc": "用跨平台框架flutter来写app页面的初体验",
"where": "6F-17会议室",
"startTime": 1548842400
},
{
"shareId": 1238274,
"title": "Cordova原理",
"desc": "一起来了解一下Cordova",
"where": "6F-19会议室",
"startTime": 1548842400
}
]
}
Так что, если вы используете GraphQL?
query shareDetailPage($shareId: Int!, $creatorId:ID!, $start: Int!, $limit: Int = 10) {
# 分享详情
shareDetail: share (shareId: $shareId) {
shareId: id
title
desc
where
logoUrl
attchments
}
# 评论信息
commentInfo(shareId: $shareId, start: $start, limit: $limit) {
totalCount
comments {
id
userId
content
commentTime
}
}
# TA的分享
hisShares (creatorId: $creatorId) {
shares {
title
desc
where
startTime
}
}
}
Один запрос может сделать это.
операция мутации
Операция изменения, здесь представлен только один сценарий. Когда дело доходит до страницы сведений о совместном использовании, нам может потребоваться отредактировать совместное использование.Традиционным способом нам нужно вызвать интерфейс операции обновления:
POST /api/share/update/:shareId
FormData:
title=xxx&desc=xxx&where=xxx
После настройки этого интерфейса, чтобы подтвердить, что обновление прошло успешно, мы также можем снова вызвать интерфейс для получения и обмена данными:
GET /api/share/:shareId
Далее переключаемся на GraphQL:
mutation editShareInfo($shareObj: ShareInput!) {
editShareInfo(shareInfo: $shareObj) {
shareId: id
title
desc
where
logoUrl
attchments
}
}
Таким образом, вы можете напрямую изменять общий контент и возвращать измененные данные общего доступа.
другие функции
Для того, чтобы мы могли написать часть кода оператора запроса для лучшего повторного использования,GraphQL
также обеспечиваетFragments
(фрагмент),Inline Fragments
(встроенный фрагмент) иDirectives
(командная) функция. Первые два можно сравнить с JavaScriptfunction
(функция) иanonymous function
(анонимная функция),Directives
(Инструкция) может решить, нужно ли возвращать некоторые поля в соответствии с параметрами, которые мы передаем. Я не буду вдаваться в подробности здесь.
Как достичь вышеуказанных функций?
schema
В приведенном выше примере определенно возникнут некоторые вопросы: как узнать, какие поля можно запрашивать? Какие параметры используются? Это требует введенияschema
.
С точки зрения непрофессионала,schema
Это соглашение, спецификация или может быть, когда он является интерфейсным документом.
GraphQL указывает, что каждыйschema
Есть корневой (корневой) запрос и корневая (корневая) мутация.
Давайте сначала посмотрим, как написать корневой запрос, который по-прежнему является примером вышеприведенного запроса.
# 定义一个根查询
type Query {
# 可以查询的字段和参数
shares(start: Int = 0, limit: Int = 10, creatorId: ID): [Share!]!
share(shareId: ID!): Share!
commentInfo(shareId: ID!, start: Int = 0, limit: Int = 10): CommentInfo!
}
тип данных
Если вы знакомы с TypeScript или Flow, приведенные выше обозначения могут показаться вам знакомыми, да, смысл внутри — это то, что вы думаете. За параметром каждого поля, которое можно запросить, будет следовать тип параметра,!
Используется для указания того, что этот параметр не может быть пустым.[]
Это поле указывает на то, что запрос возвращает массив,[]
Внутри находится тип массива.
Выше мы также видели некоторые типы, не существующие в TypeScript, такие какID
,ID
Давайте пока будем относиться к нему как к строкеString
тип в порядке. Подобно знакомому JavaScript или TypeScript,GraphQL
Также существует несколько базовых типов, вGraphQL
они все вместе называются标量类型
(Scalar Type), в том числе: Int (целое число), Float (число с плавающей точкой), String (строка), Boolean (логическое значение) и ID (уникальный тип идентификатора). в то же время,GraphQL
Также позволяют настроить Scalar Type, например: тип даты, просто реализуйте соответствующую сериализацию, обратная последовательность и проверку.
тип объекта
В приведенном выше определении корневого запроса мы также видим некоторые типы, связанные с бизнесом, такие как «Поделиться», «Комментарий», которые вместе называются对象类型
. Тип объекта такжеGraphQL
серединаschema
Он может сказать нам, какие объекты доступны на сервисе и какие поля есть у этого объекта. Следующее, что нам нужно сделать, это определить эти типы объектов, пока все они не станут базовыми типами.
# 定义Share的对象类型
type Share {
id: ID!
title: String!
desc: String!
startTime: Int!
where: String
attchments: String
logoUrl: String
creatorId: ID!
lastUpdateTime: Int
is_delete: Int
score: Int
createTime: Int!
}
# 定义评论信息对象类型
type CommentInfo {
totalCount: Int!
comments: [Comment!]!
}
# 定义评论对象类型
type Comment {
id: ID!
content: String!
commentTime: Int!
userId: ID!
shareId: ID!
}
Таким образом, мы завершили определение схемы.
Другие типы и функции
GraphQL
На самом деле естьEnumeration types
(тип перечисления),Union types
(тип сустава). В то же время, чтобы лучше повторно использовать код,GraphQL
также обеспечиваетInterface
(интерфейсная) функция. Я не буду вдаваться в подробности здесь.
реализация
GraphQL
По соглашению нам нужно предоставить по одному для каждого поля внутри корневого запроса и корневой мутации.resolver
Функция. И оберните его в объект, чтобы выставить его, например:
const resolvers = {
// 这里面写查询操作字段的resolver函数
Query: {},
// 这里面写变更操作字段的resolver函数
Mutation: {},
}
export default resolvers
Давайте продолжим и напишем полное:
// 一些加载数据的async function
import { loadSharesFromDB, loadShareById, loadCommentsByShareId } from './datasource'
const resolvers = {
// 这里面写查询操作字段的resolver函数
Query: {
shares: (parent, { start, limit, creatorId }, context, info) => {
return loadSharesFromDB(start, limit, creatorId)
.then(...)
},
share: (parent, { shareId }, context, info) => {
return loadShareById(shareId)
.then(...)
},
commentInfo: (parent, { shareId, start, limit }, context, info) => {
return loadCommentsByShareId(shareId, start, limit)
.then(...)
},
},
// 这里面写变更操作字段的resolver函数
Mutation: {
// ...
},
}
Точно так же дляmutation
(изменение) операции, мы также сначала ставимschema
Заканчивать:
# 定义Mutation根入口
type Mutation {
editShareInfo(shareInfo: ShareInput!): Share!
}
input ShareInput {
id: ID!
title: String!
desc: String!
where: String
}
Затем завершитеresolver
функция:
import { updateShareInfo, loadShareById } from './datasource'
const resolvers = {
Query: {
// ...
},
Mutation: {
editShareInfo: (parent, { shareInfo }, context, info) => {
// 更新分享详情,then获取更新后的分享详情
return updateShareInfo(shareInfo.id, shareInfo)
.then(loadShareById(shareInfo.id))
},
},
}
export default resolvers
До сих пор мы достигли этого простогоGraphQL
Сервер поднят.
Эпилог
GraphQL
Есть еще много чего исследовать, использовать. Например, если вы используете функцию построения схемы для создания типа объекта, вы можете пометить поле как устаревшее и указать причину устаревшего. Таким образом, когда версия повторяется, пользователям старой версии может быть предложено обновить интерфейс до последней версии.С помощью некоторых методов обнаружения мы также можем легко узнать частоту использования старой версии, чтобы было удобно let В какой-то момент мы полностью удалили это поле.
если мы предположимGraphQL
Каковы недостатки, которые могут заключаться в том, что действительно не так просто начать работу, и для студентов, изучающих бэкэнд, все еще есть много ям, на которые нужно наступить, таких как кеш, проблемы с производительностью и т. д. К счастью, текущийGraphQL
Информация народа уже не так скудна, как несколько лет назад, будь то официальная или общественная,GraphQL
Появляется все больше и больше ресурсов и решений, на которые можно ссылаться.
В любом случае, чисто для внешнего интерфейса, если последним технологическим изменением внешнего интерфейса была популяризация SPA, я считаю, что когда придет следующее изменение, должно бытьGraphQL
тень.
некоторые ссылки
- GraphQL Tutorials
- Учебное пособие по китайскому языку GraphQL
- Жарко на ЧжихуПочему GraphQL не прижился?
-
graphpackКонфигурация 0
GraphQL server
Инструмент, очень подходящий для начинающих, чтобы понятьGraphQL
, и предоставляет метод Codepen для редактирования кода онлайн.Примеры в этой статье реализованы на основе этого инструмента.