Skip to content

RayProud/aviasales-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Тестовое задание Aviasales

TL;DR

  • aviasales.rayproud.now.sh;
  • Сделано на базе Create React App;
  • TypeScript, React, Redux, Redux-Saga, Web Workers, Grid Layout;
  • Времени потрачено примерно пять вечеров.

Поднять у себя

  1. git clone git@github.com:RayProud/aviasales-test.git
  2. cd aviasales-test
  3. npm i
  4. npm start
  5. (если само не) Открыть в браузере localhost:3000

Что умеет приложение

Задание сделано по следующей доке, а работа с сервером по этой доке.

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

После этого запросы и сортировка продолжаются и на каждую 10ю пачку запросов воркер отправляет в приложение новые ТОП-5 билетов, пока не сервер не скажет, что билеты закончились. Только после этого начинают работать фильтры по пересадкам. Что, теоретически, может привести к введению пользователя в заблуждение, если он доберется до фильтров быстрее, чем закончится поиск. Но эту проблему я решить не успел, только придумал несколько решений. Варианты решения проблемы:

  • Блокировать прелоадером фильтры (что не очень хороший UX),
  • Написать очередь сообщений в воркере, чтобы он отфильтровал после того, как закончит с поиском (но для этого придётся ставить прелоадер на фильтры после клика, чтобы запретить в эту очередь допушивать),
  • Может использовать SharedWorker, чтобы пока один заканчивает поиск, второй мог бы фильтровать по тем билетам, что уже есть.

Каждый запрос (на пачку билетов) ограничен таймаутом в две секунды и пятью запросами. Если запрос падает больше пяти раз, то воркер пошлёт сообщение об ошибке и в интерфейсе появится загрушка, говорящая о проблеме.

Если все фильтры пересадок были выключены, то показывается плашка с сообщением, что без фильтров непонятно, что именно искать.

Также, у приложения есть простенькая мобильная версия с просто переставленными блоками в одну колонку.

Про техническую часть

В качестве бойлерплейта был взят Create React App, для того, чтобы не тратить время на сетап всего окружения. Для меня важно было, что там уже есть поджержка TS, React, Webpack и минимум post-css.

Для работы с сайд-эффектами была взята Redux-Saga. Выбрана она была не только потому что там, на мой взгляд, удобно можно описывать бизнес-логику конкретного сценария в одной функции-генераторе, но ещё и потому что там есть eventChannel, позволяющий связать сообщения от чего-то вне реакта/редакса (в моём случае с Web Worker'ом) со store'ом.

Чтобы не блокировать основной поток JavaScript'а постоянными запросами и сортировкой потенциально больших данных, было решено всю работу с данными вынести в Web Worker. Именно там делаются все запросы, сортируются по фильтрам (по тем, что есть) и через postMessage отправляются в основной поток, где его ловит подписанная на эти сообщения сага.

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

Тонкий момент

Выбирая CRA, я помнил, что в нём умеют работать с Service Worker, что заставило меня думать, что и Web Worker'ы они готовить умеют. Потратив какое-то неприятное количество времени на то, чтобы узнать, что поддержка их будет в следующем минорном релизе react-scripts, а также, что костылей написано уже почти с десяток, но только ни один из них не может в TS, было решено, что npm run eject (чтобы вынести все файлы настроек из react-scripts в репу проекта) я делать не буду и просто положил его [файл web worker'а] голым JavaScript'ом в public/. Поэтому там без типизации, сборка про этот файл ничего не знает и в идеале бы это поправить. Сам файл можно посмотреть в public/worker.js.

Что хотелось бы, но не сделано

  • Тесты;
  • Прелоадер в самом начале, когда, теоретически, долго может не появляться партия билетов;
  • Прелоадер-полоса, чтобы показать, что процесс допушивания/досортировывания билетов ещё идёт;
  • Сообщение о том, что поиск устарел и нужно перезапросить данные;
  • Указывать +N дней, если прилёт не в тот же день, когда вылет;
  • Собирать worker.js тайпскриптом в отдельный файл;
  • Prettier, который бы всё причесал.

Команды

npm start

Чтобы поднять приложение на localhost:3000

npm run build

Чтобы сбилдить про-версию приложения

npm run eject

Чтобы вытащить все скрипты сборки из react-scripts в сам репозиторий

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published