Урок 25 из 49 · Месяц 3. JavaScript, часть 2

Презентация проектов. Итоговая работа месяца

Содержание урока

Этот урок завершает месяц JavaScript. Вы научились проверять текст регулярками, работать с асинхронностью и промисами, отправлять запросы на сервер, обрабатывать формы и подключать пакеты через npm. Теперь соберём всё в проект, который не стыдно показать: оформим README, опубликуем сайт на GitHub Pages, подготовим короткую презентацию и проверим себя на итоговой контрольной работе.

Какой проект подойдёт для презентации

Хороший учебный проект месяца — небольшое, но законченное приложение, которое работает с API. Несколько идей:

  • Каталог пользователей — список с поиском, страница профиля с постами (JSONPlaceholder /users, /posts).
  • Список задач с сервером — загрузка, добавление, отметка выполнения и удаление задач (/todos, все методы CRUD).
  • Мини-блог — лента постов, форма нового поста с валидацией, комментарии к посту.

Что обязательно должно быть в проекте:

Требование Тема месяца
Загрузка данных с сервера через fetch и async/await fetch и GET
Индикатор загрузки и понятное сообщение об ошибке try, catch, finally
Хотя бы одна форма с проверкой и отправкой POST формы и POST
Изменение или удаление данных (PUT/PATCH/DELETE) REST API
Проверка ввода регулярным выражением регулярные выражения
Аккуратная структура файлов и package.json npm

Приводим код в порядок

Перед показом пройдитесь по чек-листу:

  • Структура файлов понятна с первого взгляда:
my-project/
├── index.html
├── style.css
├── js/
│   ├── main.js      // точка входа: обработчики событий
│   ├── api.js       // все запросы к серверу
│   └── render.js    // функции отрисовки
├── README.md
└── .gitignore
  • Нет мусора: закомментированного старого кода, лишних console.log, неиспользуемых файлов.
  • Понятные имена: renderPosts, createPost, а не func1, a, data2.
  • Запросы вынесены в отдельный файл — так проще найти и поменять адрес сервера.

Пример api.js с экспортом функций:

// js/api.js
const API_URL = "https://jsonplaceholder.typicode.com";

async function request(path, options = {}) {
  const response = await fetch(`${API_URL}${path}`, {
    headers: { "Content-Type": "application/json" },
    ...options,
  });
  if (!response.ok) throw new Error(`Ошибка ${response.status}`);
  return response.status === 204 ? null : response.json();
}

export const getPosts = () => request("/posts?_limit=10");
export const createPost = (post) =>
  request("/posts", { method: "POST", body: JSON.stringify(post) });
export const deletePost = (id) => request(`/posts/${id}`, { method: "DELETE" });
// js/main.js
import { getPosts } from "./api.js";

const posts = await getPosts();
console.log(posts.length); // 10

Чтобы import работал в браузере, подключите скрипт как модуль: <script type="module" src="js/main.js"></script>, а страницу открывайте через Live Server, а не двойным кликом.

README — лицо проекта

README.md — файл, который GitHub показывает на главной странице репозитория. По нему человек за 30 секунд понимает, что это за проект и как его запустить. Пишется на Markdown — простой разметке, где # — заголовок, - — пункт списка.

Шаблон хорошего README:

# Мини-блог

Учебный проект: лента постов с добавлением и удалением записей.
Данные — тестовый API JSONPlaceholder.

**Демо:** https://ваш-логин.github.io/mini-blog/

## Возможности

- загрузка постов с сервера (GET)
- добавление поста через форму с валидацией (POST)
- удаление поста с подтверждением (DELETE)
- индикатор загрузки и обработка ошибок

## Технологии

HTML, CSS, JavaScript (fetch, async/await), JSONPlaceholder

## Как запустить

1. Склонировать репозиторий: git clone https://github.com/ваш-логин/mini-blog.git
2. Открыть папку в VS Code
3. Запустить index.html через Live Server

## Что я узнал

- как работать с REST API и обрабатывать ошибки запросов
- как собирать данные формы через FormData

Главное — ссылка на демо в самом начале (большинство хочет просто посмотреть), короткий список возможностей и пошаговая инструкция запуска. Скриншот можно добавить, когда проект будет готов.

Публикация на GitHub Pages

GitHub Pages — бесплатный хостинг статических сайтов прямо из репозитория GitHub. Наш проект на HTML, CSS и JS — как раз статический сайт.

Вариант 1. Проект без сборщика

Если проект — это просто index.html, CSS и JS-файлы:

  1. Отправьте проект на GitHub (вспомните урок про Git):
git add .
git commit -m "Готовый проект для презентации"
git push origin main
  1. Откройте репозиторий на GitHub → Settings → Pages.
  2. В блоке Build and deployment выберите Source: Deploy from a branch.
  3. Выберите ветку main и папку / (root), нажмите Save.
  4. Через минуту-две на этой же странице появится адрес вида https://ваш-логин.github.io/имя-репозитория/.

Вариант 2. Проект на Vite

Если вы собирали проект через Vite, публиковать нужно не исходники, а собранную папку dist. Сначала укажите в vite.config.js адрес, по которому будет открываться сайт:

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  base: "/mini-blog/", // имя вашего репозитория между слешами
});

Без base браузер будет искать файлы в корне домена ваш-логин.github.io/, а не в папке репозитория, и страница окажется пустой.

Дальше удобнее всего настроить автоматическую публикацию через GitHub Actions. Создайте файл .github/workflows/deploy.yml:

name: Deploy to GitHub Pages

on:
  push:
    branches: [main]

permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: lts/*
          cache: npm
      - run: npm ci
      - run: npm run build
      - uses: actions/configure-pages@v5
      - uses: actions/upload-pages-artifact@v4
        with:
          path: dist
      - id: deployment
        uses: actions/deploy-pages@v4

При каждом push в main GitHub запустит виртуальный компьютер, установит зависимости строго по package-lock.json (npm ci), соберёт проект в dist и опубликует его на Pages.

В настройках репозитория Settings → Pages выберите Source: GitHub Actions. Прогресс публикации видно на вкладке Actions. Подробнее — в документации Vite о деплое и документации GitHub Pages.

Проверка после публикации

  • Откройте сайт в режиме инкогнито и на телефоне, пройдите весь сценарий пользователя.
  • В DevTools на вкладках Console и Network не должно быть красных ошибок и ответов 404.

Как презентовать проект

На презентацию обычно даётся несколько минут. Удобный план на 3–5 минут:

  1. Что это и зачем (30 секунд): «Это мини-блог. Можно читать посты, добавлять и удалять их».
  2. Живая демонстрация (2 минуты): покажите главный сценарий от начала до конца. Не показывайте каждую кнопку — покажите путь пользователя.
  3. Что внутри (1 минута): одна-две интересные части кода. Например, функция request и обработка ошибок или валидация формы.
  4. Что было сложно и как решили (30 секунд): честный рассказ о проблеме ценится выше, чем «всё было легко».
  5. Планы (15 секунд): что хотели бы добавить.

Будьте готовы к вопросам: «Что будет, если сервер не ответит?», «Чем PUT отличается от PATCH?».

Повторение ключевых тем месяца

Тема Главное
Регулярные выражения /шаблон/флаги, test, match, replace; ^ и $ для проверки всего поля
Рекурсия функция вызывает себя; обязателен базовый случай
Event Loop синхронный код → микрозадачи (промисы) → макрозадачи (setTimeout)
Promise pending → fulfilled/rejected; .then, .catch, .finally, Promise.all
Ошибки try/catch/finally, throw new Error(), ошибки в колбэках ловим внутри колбэка
fetch и async/await await fetch(url), проверка response.ok, await response.json()
Формы label + name, событие submit, preventDefault, FormData
REST и HTTP ресурсы и адреса, методы GET/POST/PUT/PATCH/DELETE, статус-коды, HTTPS
npm package.json, npm i, -D, scripts, node_modules в .gitignore

Чек-лист: что нужно уметь

  • Написать регулярку для проверки email, телефона или пароля и использовать replace с флагом g.
  • Написать рекурсивную функцию для обхода вложенного массива или дерева.
  • Объяснить, в каком порядке выполнится код с setTimeout и Promise.then.
  • Создать свой промис через new Promise и обработать оба исхода.
  • Запустить несколько запросов параллельно через Promise.all.
  • Обработать ошибку через try...catch и спрятать индикатор загрузки в finally.
  • Сделать GET-запрос, проверить response.ok и вывести данные на страницу через textContent.
  • Собрать данные формы, проверить их и отправить POST-запросом.
  • Изменить и удалить запись методами PUT/PATCH и DELETE.
  • Создать проект через npm init, установить пакет, добавить скрипт и .gitignore.
  • Опубликовать проект на GitHub Pages и написать README.

Пример итоговой контрольной работы

Ниже — пример того, как может выглядеть контрольная. Формат и время реальной работы объявит ментор.

Часть 1. Теория (устно или письменно)

  1. Что выведет этот код и почему?
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
  1. Чем отличается Promise.all от Promise.allSettled?
  2. Почему fetch не попадает в .catch при ответе 404 и как это обработать?
  3. Чем PUT отличается от PATCH? Какой статус-код обычно возвращает успешный POST?
  4. Зачем нужен event.preventDefault() в обработчике submit?
  5. Что такое devDependencies и почему node_modules не добавляют в Git?

Часть 2. Задачи на код

  1. Регулярка. Напишите функцию isValidLogin(str): логин из 4–16 символов, только латинские буквы, цифры и _, начинается с буквы. Проверьте на "anna_99" (true), "9anna" (false), "an" (false).
  2. Рекурсия. Напишите функцию flatten(arr), которая превращает [1, [2, [3, [4]]], 5] в [1, 2, 3, 4, 5], не используя встроенный метод flat.
  3. Промис. Напишите функцию delay(ms, value), которая возвращает промис, выполняющийся через ms миллисекунд со значением value. Через Promise.all дождитесь трёх таких промисов и выведите массив значений.

Часть 3. Практическое задание

Сделайте страницу «Задачи пользователя» на API https://jsonplaceholder.typicode.com:

  1. При загрузке страницы получите список пользователей /users и выведите их в <select>.
  2. При выборе пользователя загрузите его задачи /todos?userId=N и выведите списком; выполненные — зачёркнутым текстом.
  3. Во время загрузки показывайте «Загрузка...», при ошибке — понятное сообщение.
  4. Добавьте форму «Новая задача» с проверкой (не пустая, не короче 3 символов). При отправке — POST на /todos, новая задача появляется в начале списка.
  5. У каждой задачи кнопка «Удалить» (DELETE) с подтверждением.
  6. Опубликуйте результат на GitHub Pages и приложите README.

Пример того, как может начинаться решение:

const API_URL = "https://jsonplaceholder.typicode.com";
const select = document.querySelector("#user-select");

async function loadUsers() {
  const response = await fetch(`${API_URL}/users`);
  if (!response.ok) throw new Error(`Ошибка ${response.status}`);
  const users = await response.json();

  users.forEach((user) => {
    const option = document.createElement("option");
    option.value = user.id;
    option.textContent = user.name;
    select.append(option);
  });
}

loadUsers().catch((error) => {
  console.error(error);
  select.disabled = true;
});

Как подготовиться

  • Набирайте примеры руками, а не копируйте — так код запоминается лучше.
  • Объясните тему вслух. Смогли объяснить другу Event Loop — значит, поняли.
  • Сделайте практическую часть заранее с таймером.
  • Читайте ошибки в консоли и смотрите вкладку Network.
  • Пользуйтесь документацией — например, MDN Web Docs.

Практика

  1. README. Напишите README для своего проекта по шаблону из урока: описание, ссылка на демо, возможности, технологии, как запустить.
  2. Публикация. Опубликуйте проект на GitHub Pages и проверьте его в режиме инкогнито и с телефона. В консоли не должно быть ошибок.
  3. Презентация. Подготовьте рассказ о проекте по плану из пяти пунктов и отрепетируйте его с таймером: уложитесь в 5 минут.
  4. Контрольная — часть 2. Решите три задачи на код и проверьте их в консоли браузера.
  5. Контрольная — часть 3. Выполните практическое задание «Задачи пользователя» целиком и отправьте ментору ссылку на репозиторий и демо.

Итоги

  • Проект для презентации — небольшой, но законченный и работающий с API.
  • Перед показом наведите порядок: структура файлов, понятные имена, запросы в отдельном модуле, никаких ключей в коде.
  • README отвечает на вопросы «что это», «где посмотреть» и «как запустить».
  • GitHub Pages публикует статический сайт из ветки, а проект на Vite — через GitHub Actions с настроенным base.
  • Презентация: что это → живое демо → интересный код → сложности → планы.
  • Чек-лист и пример контрольной помогут понять, какие темы стоит повторить.
Отзыв