MODXCLUB

Николай Ланец
25 авг. 2017 г., 0:00

React-js. Урок №2. Запросы с помощью GraphQL

Всем привет!

Сегодня, что называется, из огня да в полымя:) Вот краткое видео, что я вам хочу сегодня представить:

Это конструктор запросов от фейсбука. Более подробное и внятное вступление читайте здесь: https://habrahabr.ru/post/326986/

Честно сказать, я его тоже только-только осваивать начал, но все-таки что-то уже получилось и оно работает. Вот демка: https://modxclub.ru/react-lessons/lesson2
Демка работает с реальной базой данных, хоть и возвращает всего несколько записей. Позже прокачаю ее получше.

Зачем вообще было включать это в виде второго урока?

На самом деле это, на мой взгляд, одна из трех основ построения веб-приложений на реакте.

1. Интерфейсы (react-компоненты). То, что отвечает за отображение в принципе.
2. Хранилища (flux и всякие его производные (redux и т.п.)).
3. Клиент-серверные запросы. Это как раз и обеспечивает GraphQL.

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

На самом деле я даже не могу особо здесь что-то написать сейчас :) Но надеюсь, что исходные коды будут в помощь, и если кому что-то будет не ясно, но захочется прояснить, спрашивайте. Напомню, что исходники лежат здесь: https://github.com/MODX-Club/react-study
Как устанавливать и запускать, я писал в предыдущем уроке https://modxclub.ru/topics/react-js.-urok-%E2%84%961.-byistryij-start-2616.html
Где что самое интересное лежит:

Коротко принцип работы.

На фронте формируется схема запросов, что дает возможность в пользовательском интерфейсе выдавать подсказки какие объекты и какие поля для них можно получить. Далее формируется запрос и отправляется на сервер, где используется почти такая же схема, но с описанными резолверами, то есть функциями, которые обрабатывают эти запросы. Это могут быть любые функции, работающие с любыми источниками данных (готовые массивы данных, mysql-клиенты, rest-клиенты и т.п., все что угодно). Формируется ответ и отправляется клиенту.

Преимущество здесь в том, что вы можете описать объекты запросов, которые могут быть использованы на разных уровнях запросов. К примеру у меня это Пользователи и Ресурсы. При этом запрос Ресурсы используется как на первом уровне самостоятельно (список всех ресурсов), так и дочерним для Пользователей (список документов, созданных пользователем, то есть для каждого пользователя выполняется выборка его документов).

Второе преимущество здесь заключается в том, что резолверы здесь работают асинхронно для разных запросов, но в целом обеспечивается механизм обеспечения последовательности для вложенных запросов. То есть, если вы запросили сразу список пользователей и ресурсов
query{ users { id username } resources { id pagetitle } }
он не будет дожидаться когда придет ответ для users, чтобы выполнить запрос resources, а выполнит параллельно оба запроса, но вернет ответ только когда будут получены все ответы.

А вот такой запрос уже хитрее будет:
query{ users { id username #документы, созданные пользователем resources { id pagetitle } } resources { id } }
Здесь он, когда получит пользователей, для каждого из них отправит запрос на получение документов пользователя. Но опять-таки, документы он уже будет получать параллельно, то есть для 10-ти пользователей выполнит 10 параллельных запросов и ответы может получить в разной последовательности, но ответ общий вернет в той последовательности, в которой были получены пользователи.

В общем, на первый взгляд преимущества могут не быть очевидными, но лично я очень рад этому инструментарию. Скоро реализую некоторые свои идеи, надеюсь вам тоже понравится.
Действительно очень нужный инструмент. Позволяет навести порядок в запросах к серверу
мне понравилось, поюзал :D правда практического применения пока не было, но уже преставляю где можно использовать
На простых сайтах, конечно, это решение скорее всего будет избыточным. Но на сайтах покрупнее очень даже нужная штука. Вот смотри структура данных здесь (далеко не полная):
Пользователь
Команда
Работа портфолио
Вид деятельности
Топик
Комментарий

Когда по отдельности берешь эти данные, тогда еще ничего. А когда надо, к примеру, такое получить:
Список пользователей
По каждому пользователю список его работ
В каждой работе получить список участников работы
По каждому участнику получить список направлений, по которым он участвовал в проекте
По каждому направлению получить сколько всего работ по данному направлению есть
Сколько компаний работает по данному направлению
и т.д. и т.п.

Уровней вложенности может быть очень много. И каждому может понадобиться свой набор данных. Попробуй-ка на классических технологиях такое реализовать (конструктор запросов).
Николай, большое спасибо за уроки! Намереваюсь попробовать Vulcan.js

ОК. Как будут результаты, если что, напишите небольшой топик что и как там работает, плиз.
А я свой один проект переделываю, полностью на JS. Очень интересные техники новые освоил, и в GraphQL продвинулся. Скоро новые уроки появятся.
Николай, вижу мой совет про graphql в первом уроке был принят ))). Благодарю за этот урок, Вы занимаетесь хорошим делом! Хотел бы добавить в преимущества:

1. Структура ответа всегда точно повторяет структуру запроса, все сталкивались с проблемой когда в ресте поменялась структура объекта в ответе и все ломалось. И версионность больше не нужна по этой причине.

2. Возможность работать сразу с несколькими источниками данных. Поскольку по сути graphql это агрегатор, мы можем накрутить работу сразу с несколькими базами и соединять данные в одну выборку.

3. Быстро разворачивается в сравнении с рест. Если написать генератор для моделей, вообще за 5 минут. И за счёт того, что всего 1 эндпоинт мы получаем полнофункциональный вариант по сути, только связи руками накрутить. Ну исключение с мутациями, на них генератор не сделать.
Да, Артем, сейчас граф - один из моих основных инструментов и ввел я его уже на нескольких проектах. Очень круто он себя показывает при внедрении на уже готовые проекты. К примеру, не так давно я анонсировал запуск проекта http://troika-gorod.ru/ , который написан полностью на JS, а MODX используется только для проброса и модификации API-запросов. И вот они обратились за доработками, и я решил, что раз функционал растет, то имеет смысл граф ввести, чтобы потом не было мучительно больно. Отмечу, что ввести граф, на самом деле - это совсем не 5 минут (если сайт - не сайт-визитка), во всяком случае у меня. Я руками все пишу. По моим наблюдениям, на среднем проекте только листинг основных запросов составляет строк 500, и это еще при условии использования фрагментов, которые вставлять можно в разные части. На тройке - это 1000 строк. Все это - три десятка АПИ-запросов. http://joxi.ru/bmoY6bGSMdRzpA

Так вот, здесь себя граф показывает не только как отличное средство для построения запроса, но и как архитектор АПИ. Вот пара примеров с этой тройкой:

Справа - это предоставленная документация. Видно, что вкралась опечатка.

А вот еще:

А вот пример, почему такое невозможно с графом:

А вот наглядный пример, для чего это делается: вот я одним запросом получаю сразу три блока информации http://joxi.ru/bmoY6bGSMdRJpA

При чем в своем конечном ответе я получаю именно один конечный многоуровневый JSON. А то, что граф выполнил для сбора этой информации три запроса - так это как раз и демонстрирует то, о чем говорит Артем - возможность работать сразу с несколькими источниками данных. Здесь три запроса выполняется только потому, что на стороне сервера не работает граф и он просто не может вернуть данные одним ответом. А вот на другом моем проекте (и не только на нем), граф крутится и на сервере и в ответе в одном я получаю все нужные мне данные

Кстати, в связке с сервером, у меня получилась вообще очень интересная связка: у меня и на сервере, и на клиенте используется единая схема. Это позволяет, во-первых, на сервер в запросе слать не портянку, а просто название операции с параметрами. К примеру, на получение этих данных отправляется вот такой запрос:

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

Короче, про него можно очень много всего рассказывать. И надо отметить, что работа с ним - это не всегда праздник. В том же браузере, из-за того, что он использует промисы, он не рассчитан на множественный вызов (то есть когда во внутренних резолверах выполняешь еще запросы на граф). В случае сотен вызовов в рамках одного запроса, выборка конечная может составить 10 секунд и более :) Но если правильно оптимизировать все, то этот же объем данных будет получен менее чем за секунду.
Николай, да тут смысл в том, чтобы одним запросом к серверу получать сразу все данные. Кстати этот момент хорошо работает и в случае с серверным рендерингом. Мы любые данные можем получить одним запросом и не нужно ничего комбинировать или слать несколько. Поскольку серверный рендеринг работает синхронно это огромное преимущество. Во первых мы не перегружаем локальный сокет петлями, во вторых один запрос (который распараллелить внутри GraphQL) выполняется значительно быстрей, что напримую влияет на первую выдачу HTML в браузер

С ошибками Вы точно подметили, один из значимых плюсов!. Стоит тоже в статью добавить )). Примеры отличные !)
Предлагаю следующий урок посвятить серверному рендерингу :)

Добавить комментарий