Как организовать бизнес-логику для профайл экрана с множеством запросов
Что проверяют
Умеете ли вы разложить экран с пятью-шестью независимыми источниками данных так, чтобы контроллер или View не превратились в клубок колбэков. Главный подвопрос: что показать, если три запроса прошли, а один упал. Следом часто спрашивают про отмену запросов и тесты.
Как отвечать
Каркас ответа:
- слои: View только рисует состояние, ViewModel (или Presenter с Interactor в VIPER) держит логику экрана, под ним сервисы по доменам:
ProfileService,StatsService,SubscriptionService. Каждый закрыт протоколом, чтобы подменить его в тестах; - параллельные запросы: независимые данные грузите одновременно, а не цепочкой. В Swift Concurrency это
async letдля фиксированного набора илиwithThrowingTaskGroupдля динамического. Зависимые запросы, где сначала нуженuserId, идут последовательно; - состояние по секциям: не один флаг
isLoadingна экран, а своё состояние у каждого блока, напримерenum Loadable<T> { case loading, loaded(T), failed(Error) }. Тогда упавшие достижения не ломают весь профиль; - обязательные и необязательные данные: без основного профиля экран показывает ошибку с кнопкой повтора, без статистики показывает остальное и заглушку в блоке;
- главный поток: ViewModel помечается
@MainActor, с iOS 17 удобен макрос@Observable. В Swift 6 со строгой проверкой конкурентности модели ответов должны бытьSendable; - отмена и кеш: модификатор
.taskв SwiftUI сам отменяет задачу при уходе с экрана, в UIKit хранитеTaskи отменяйте его вviewDidDisappear. Кешированный профиль можно показать сразу и обновить после ответа.
Если запросов действительно много, предложите агрегирующий эндпоинт на бэкенде (BFF): один запрос вместо шести экономит батарею и время в мобильной сети.
Где спотыкаются
Складывают всё в UIViewController или во View: десятки колбэков, флаги загрузки и навигация в одном файле.
Грузят данные цепочкой вложенных замыканий, хотя запросы независимы, и экран открывается в разы дольше.
Делают «всё или ничего»: любой упавший запрос показывает ошибку на весь экран. Или забывают про отмену, и ответ приходит в уже закрытый экран, обновляя то, чего никто не видит.