#Задание
Склонируйте код из репозитория: git clone https://github.com/shri-msk-2016/task3.git
Выполните npm install
, а затем npm start
и откройте приложение в браузере (http://localhost:3000).
Приложение позволяет добавлять и редактировать данные студентов ШРИ (ФИО, ссылку на фотографию и краткую информацию). Для работы в офлайне оно использует ServiceWorker, позволяя при этом, как минимум, просматривать данные студентов.
Однако при реализации были допущены несколько ошибок:
- Без подключения к серверу приложение не работает.
- Не всегда обновляется список студентов после добавления нового.
Найдите и исправьте ошибки. В качестве дополнительного задания вы можете реализовать добавление студентов в офлайне с последующей синхронизацией. При выполнении обратите внимание на способы определения режима «онлайн/офлайн».
Результат пришлите в виде ссылки на https://github.com
##Что мы проверяем этим заданием?
Мы хотим проверить вашу способность разобраться в незнакомом коде и/или API. Также с помощью этого задания мы оценим ваш навык отладки. Поэтому прокомментируйте, пожалуйста, в коде или текстовом файле README ход ваших мыслей — какие ошибки и как вы нашли, почему они возникли и какие способы исправления существуют. Мы не ограничиваем вас в использовании сторонних инструментов и библиотек, однако при их использовании также ожидаем комментариев, в которых вы расскажете, зачем и почему было использовано то или иное средство.
-
Запуск исходного приложения. В консоле быпадает ошибка и жалуется на 36 строку в worker.js
-
Проблема была в ";". Удаляем лишний знак и перезагружаем страницу. Теперь во вкладке Resources видим, что worker установился, но в консоле снова ошибки: не найдены файлы js и css.
-
И правда, в путях до файлов была ошибка. Исправляем пути, перезагружаем. Вуаля, worker активен, кэш загрузился. Проверим offline-режим. Глушим сервер, обновляемся...страница недоступна :(
-
Почитав статью, обнаружились следующие важные моменты в работе worker'а:
- регистрация worker'а должна проходить по HTTPS протоколу
- файл worker'а должен лежать в папке с index.html, иначе он не увидит некоторые запросы
- worker начинает работу только после того, как страница перезагружена после его установки
-
Исходя из этих моментов, понятно, что наш worker лежит глубже основного файла. Перетаскиваем его в корень и меняем путь к worker'у в index.html.
-
После обновления и еще раз обновления для начала работы worker'а видим, что теперь он делает запросы к базе студентов и к аватарке, но снова беда - ошибки в консоле, ругается на промисы. Получается следующая ситуация: мы забрали в кэш базу студентов (api/v1/students), но с аватаркой не так все просто. Она не грузится даже после нескольких обновлений... Идем в файл воркера и смотрим обработчик, перехватывающий fetch.
Тут три варианта:
- если запрос к /api/v1 и при этом не GET и не HEAD то пропускаем fetch как есть
- если GET/HEAD к /api/v1, то запускаем "гонку" промисов.
- все остальные запросы идут через getFromCache
Обратил внимание на метод Promise.race. Очень странное использование. Метод вернет результат первой выполненной функции. Изучаем функции fetchAndPutToCache и getFromCache.
- fetchAndPutToCache делает запрос и тут же кладет эти данные в кэш. Если данные не получены, то смотрит их в кэше и выдает при наличии.
- getFromCache смотрит в кэш, и, если есть данные, выдает их.
Скорее всего при вызове Promise.race первым всегда возвращается результат getFromCache, поскольку к кэшу обратиться быстрее, чем сделать запрос. Из-за этого, возможно не обновляется список студентов, поскольку в функции onStudentAddClick() вызывается функция getStudents(), которая запрашивает '/api/v1/students', а ей в ответ выдают кэш, который не был обновлен. Поэтому не видим изменений при добавлении.
Также при изучении функций заметил, что fetchAndPutToCache самодостаточна. Она выполняет ту же работу, что и getFromCache, помимо запроса и сохранения в кэше. Тогда можно заменить данную конструкцию:
if (/^\/api\/v1/.test(requestURL.pathname)) { return event.respondWith( Promise.race([ fetchAndPutToCache(event.request), getFromCache(event.request) ]) ); } return event.respondWith( getFromCache(event.request).catch(fetchAndPutToCache) );
на более простой вариант:
return event.respondWith(fetchAndPutToCache(event.request));
И в данном случае я ушел от проверки URL на наличие '/api/v1', потому что все запросы на добавление и редактирование студентов проходят в данном условии:
if (/^\/api\/v1/.test(requestURL.pathname) && (event.request.method !== 'GET' && event.request.method !== 'HEAD')) { return event.respondWith(fetch(event.request)); }
А когда мы обращаемся к базе студентов с запросом GET, то мы точно хотим положить его в кэш, следовательно проверку URL можно опустить.
-
Проверим результат изменений. Чистим кэш и удаляем worker'a, запускаем, пара обновлений, глушим сервер, обновляем..........и у нас есть список студентов в offline-режиме! Включаем сервер, пытаемся добавлять студентов...... все добавляются и сразу обновляется страница. Единственным минусом считаю долгое ожидание в режиме offline, потому что fetchAndPutToCache долго ждет ответ, а только потом заглядывает в кэш.
Получили четыре ошибки:
- поставили лишнюю ";" на 36-й строке worker'a
- положили worker'a не в ту папку
- прописали файлам для кэша неверные пути
- неправильно использовали метод Promise.race, а также использовали лишнюю функцию getFromCache