План
1) Введение
2) Принцип инверсии зависимостей и требованию реализации
3) Реализация класса для запросов
4) Выводы
Введение
Всем привет, меня зовут Александр, я являюсь фронтенд разработчиком более 4-х лет. В этой статье хочу поделится с вами своими размылениями по вопросу запросов на стороне юая и к чему я пришел в ходе своих размышлений.
Проблема, которая имеется во всем фронтенд разработке — это то, что у каждой команды/разработчика свои размышления по поводу построения запроса, то есть получается нет общепринятых рекомендаций, как строить запросы. Поэтому целью этой статьи является написание класса, который будет принимать на вход конфигурацию по настройке того или иного клиента по запросам.
Принцип инверсии зависимостей и требованию реализации
Теперь давайте обсудим более приземленное, как все начинают писать запросы на бекенд? Правильно, используем fetch или axios, более продвинутые используют для этого готовые решения на подобие rtk query или react query. Идем далее, в большинстве случаев запросы пишутся прямо возле компонента, в котором он используется, и сразу в него тянутся, при чем не важно, что здесь будет использовано санка или сага. Более продвинутые пытаются это все выносить в отдельные папки, чтобы избежать дублирования, а самые прошаренные пытаются на этом построить сущности, которая будет содержать в себе все данные по работе с запросами и саму логику их отработки, и наружу отдавать несколько методов для работы с запросами. Получается одно из требований — это построить рекомендацию для общего понимания построения сущности, в основе которой будет принцип построения запроса. Кстати, это один из принципов инверсии зависимостей, который утверждает, что наиболее гибкими получаются системы, в которых зависимости в исходном коде направлены на абстракции, а не на конкретные реализации.
Допустим, что у нас получилось построить сущность, в основании которой лежит построенный функционал по работе с апи бекенда. Но что делать, если в одном проекте используется fetch, в другом — axios, в третьем — react query? Каждый раз писать новую реализацию я думаю мало кому захочется. Что же тогда делать в таком случае? Необходимо тогда создать класс или набор функций, которые будет обрабатывать все запросы и приведет их в общий вид. Для самого класса все построенные запросы будут приходить в единооборазном виде, то есть, другими словами, для fetch, axios, react query и т. п. необходимо написать адапторы, которые их приведут к общему виду, чтобы их можно было прогнать через вышеупомянутый класс.
Также необходимо учитывать способ, которым обрабатываются запросы. Если это простой fetch или axios, то проблемы нет — они обрабатываются через функцию. Если обработка идет через rtk query, react query и тому подобное — то здесь стоит выбор через санку, другими словами функцию, или хук. Зачем я здесь акцентирую внимание? Да затем, чтобы сделать обработку вызовов единообразным. Может быть кого-то моя позиция удивит, но я придерживаюсь мнения, что лучше использовать функци, они же санки, дальше в этой статье я объясню свою позицию.
Но это еще не все, есть еще одна развилка, которая зависит от требований бизнеса и проекта. Когда строишь запросы, то они могут проходить с частичной блокировкой контента или с полной, то есть на всей странице вылезает подложка и не дает пользователю работать до тех пор, пока не закончится вызов и его обработка. Оба варианта имеют право на свою жизнь, поэтому, при проектировании вышеупомянутого класса, необходимо учитывать этот факт и сразу закладывать два сценария использования.
Реализация класса для запросов
В последнее время побывал на разных проектах и видел много реализаций для работы с запросами. И, как было описано выше, каждый реализует этот функционал по своему. В какой-то степени я понимаю, что в будущем буду также начинать проекты с нуля и хочется иметь под рукой, уже готовый каркас для работы. Для себя я уже обкатал таковой на своем блоге и в сегодняшней статье хочется поделится своими наработками, чтобы вы их оценили и, возможно, взяли себе на вооружение.
Давайте начнем, для работы с вызовами я в корне модуля проекта создаю папочку entities, чтобы на основе запросов сразу создать сущности.
Пример папки с сущностями
На изображении «Пример папки с сущностями» показано, что каждая сущность имеет свою папку. Сама может иметь следующие файлы или папки:
- service — это файл или папка, в которой прописана логика запроса по апи для общения с беком. В основном здесь прописывается rtk query;
- ducks — это файл, в котором прописывается обработка вызова функции, которая делает запрос по апи, этот файл опциональный и может отсутствовать. Например rtk query или react query предоставляют готовые хуки, в рамках которых происходит запрос данных по апи;
- slice — описывает работу глобального стора для сущности, если в этом есть необходимость, эта папка носит опциональный характер;
- hooks — выступает в роли моста между бизнес сущностью и остальным функционалом приложения, потому что именно хуки экспортируются для дальнейшего использования в приложении. Это делается для того, чтобы в дальнейшем можно было поменять функционал запроса.
Файловая структура папки с бизнес сущностью
А теперь давайте разберем, что имелось ввиду, под сменой функционал запроса данных по апи. Давайте представим, что сначала для запроса было решено использовать fetch и обертку вокруг него, потом fetch перестал устраивать и было принято решение использовать что-то другое. Вот здесь на сцену и выходит файл service и hooks. То есть в hooks и ducks можно будет прописать прослойку, которая отделит логику запросов от логики приложения и тогда функционалу приложения будет все-равно по какому способу запрашиваются данные: по первому или второму способу, вот в этом и заключается работа с запросами в моем понимании. Что еще хочется добавить из важного, экспортировать данные из сущности можно только из файла index, чтобы не вытаскивать из нее лишнего. Если из сущности что-то тянется не из корневого файла index — это является ошибкой и необходимо править.
Выводы
В этой статье я поделился своей болью по вопросу http клиента по работе с запросами и предложил свое виденье этой проблемы; может быть она не идеальная, и я это допускаю, но зато показала себя в работе на нескольких проектах максимально гибкой, что могу ее переформатировать под нужные требования. Надеюсь вам было интересно, а кому-то может быть полезно узнать что-то новое для себя. Всем спасибо за внимание и до новых встреч в последующих статьях.