GraphQL объединяет данные из нескольких вызовов REST

Я изучал некоторые реализации GraphQL и понимаю, что GraphQL позволяет вам перемещаться по данным в форме Graph.

Это означает, что вы получаете список книг, который является вызовом REST. У книг может быть имя автора.

Когда пользователь хочет получить дополнительную информацию об авторе, он говорит это, и делается еще один вызов REST для получения дополнительных сведений об этом авторе.

Точно так же в списке книг может быть поле «Издатель» и так далее. Итак, здесь вы получаете данные, как если бы вы подключали узел Book к узлу Author или Publisher.

Но я видел некоторые реализации, в которых данные из двух вызовов отдыха объединяются с использованием циклов for и отображаются в пользовательском интерфейсе. например вызовите REST API книг, затем вызовите REST API авторов, написавших эти книги. Запустите вложенный цикл for for (сложность n ^ 2), чтобы объединить результат и отобразить информацию о книгах и авторах в одном сводном представлении.

Является ли это приемлемой практикой или нарушает некоторые основные концепции того, что GraphQL не должен делать?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
0
0
2 163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен, что могу сказать, что это «нарушение некоторых основных концепций», но такой способ «предварительной загрузки» всех ваших вызовов к конечной точке REST может иметь потенциальный недостаток. GraphQL позволяет вам определять преобразователь для каждого поля, который определяет, какое значение возвращает поле. «Родительское» поле разрешается раньше, чем его «дочерние» поля, и значение «родительского» передается преобразователям для каждого «дочернего».

Допустим, у вас есть такая схема:

type Query {
  book(id: ID): Book
}

type Book {
  title: String
  author: Author
  publisher: Publisher
}

Здесь поле book будет преобразовано в объект, представляющий книгу, и этот объект будет передан преобразователям для title, author и publisher.

Если для определенного поля не предусмотрен преобразователь, поведение по умолчанию - искать свойство в родительском объекте с тем же именем, что и поле, и возвращать его. Итак, ваш преобразователь для book может получить как книгу, так и автора и издателя с некоторой конечной точки REST (всего 3 вызова) и вернуть объединенный результат. В качестве альтернативы вы можете просто получить книгу и позволить преобразователю полей author выбрать автора, а преобразователю полей publisher - издателя.

Ключевым моментом является то, что преобразователь вызывается только в том случае, если запрашивается это поле. Разница между этими двумя подходами состоит в том, что вы потенциально можете запросить book и запросить только заголовок.

query SomeQuery {
  book(id: 1) {
    title
  }
}

В этом сценарии, если вы загружаете все вызовы API заранее, вы делаете два дополнительных вызова конечной точки REST (для автора и издателя) без необходимости.

Конечно, если у вас есть поле, которое возвращает массив книг, вы можете не захотеть забивать свою конечную точку REST, выбирая автора для каждой запрошенной книги, поэтому в таких ситуациях может иметь смысл получить как книги, так и авторов всех в корневой запрос.

Здесь нет единственного правильного ответа, поскольку в любом случае возможны компромиссы. Вопрос в том, как спроектирована ваша схема, как она будет использоваться и какие затраты будут для вас приемлемы.

Другие вопросы по теме