initial commit
This commit is contained in:
463
README.md
Normal file
463
README.md
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
# Методические указания по разработке Web API на Node.js для школьников
|
||||||
|
|
||||||
|
## Введение
|
||||||
|
Данные методические указания предназначены для школьников, имеющих базовые навыки работы с HTML/CSS, Git и SSH. Цель курса — освоить основы разработки Web API с использованием Node.js и фреймворка Express за ограниченное время (3 часа на занятие и несколько занятий в семестр). Упор сделан на практические задания с минимально необходимой теорией.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📘 **Урок 1: Создание репозитория и организации структуры проекта**
|
||||||
|
|
||||||
|
### **Цель урока**: Создать GitHub-репозиторий, организовать структуру проекта и научиться работать с ветками в Git.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **GitHub** — платформа для хостинга и совместной разработки IT-проектов с использованием системы контроля версий Git.
|
||||||
|
- **Репозиторий** — хранилище кода и истории его изменений.
|
||||||
|
- **Ветка (branch)** — изолированная копия проекта для разработки новой функциональности без влияния на основной код (часто называется `main` или `master`).
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. **Создайте репозиторий на GitHub**:
|
||||||
|
* Авторизуйтесь на [GitHub](https://github.com).
|
||||||
|
* Нажмите `+` в правом верхнем углу и выберите `New repository`.
|
||||||
|
* В поле `Repository name` укажите название, отражающее тему вашего API (например, `my-first-api`).
|
||||||
|
* Оставьте репозиторий публичным (`Public`).
|
||||||
|
* **Поставьте галочку** `Add a README.md`. Это создаст начальный файл описания проекта.
|
||||||
|
* Нажмите `Create repository`.
|
||||||
|
|
||||||
|
2. **Клонируйте репозиторий и создайте учебную ветку**:
|
||||||
|
```bash
|
||||||
|
# Склонируйте репозиторий на компьютер
|
||||||
|
git clone git@github.com:<ваш-логин>/<название-репозитория>.git
|
||||||
|
cd <название-репозитория>
|
||||||
|
|
||||||
|
# Создайте и переключитесь на новую ветку 'study'
|
||||||
|
git checkout -b study
|
||||||
|
# Если в команде двое, каждый создает свою ветку (например, study-ivanov)
|
||||||
|
# git checkout -b study-фамилия
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Что должно получиться**:
|
||||||
|
* Создан удаленный репозиторий на GitHub с файлом `README.md`.
|
||||||
|
* На вашем компьютере есть локальная копия проекта.
|
||||||
|
* Вы находитесь в новой ветке (`study` или `study-фамилия`), а не в основной (`main`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 **Урок 2: Инициализация проекта Node.js**
|
||||||
|
|
||||||
|
### **Цель урока**: Создать структуру папок для backend и инициализировать проект Node.js.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **Node.js** — это среда выполнения JavaScript вне браузера, которая позволяет создавать серверные приложения.
|
||||||
|
- **package.json** — это файл манифеста проекта Node.js, который содержит его описание, версию, список зависимостей и скриптов.
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. **Создайте папку `backend`** и перейдите в неё:
|
||||||
|
```bash
|
||||||
|
mkdir backend
|
||||||
|
cd backend
|
||||||
|
```
|
||||||
|
2. **Инициализируйте проект Node.js**. Используйте флаг `-y`, чтобы принять значения по умолчанию, и `--type=module` для поддержки современного синтаксиса ES-модулей:
|
||||||
|
```bash
|
||||||
|
npm init -y --type=module
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Проверка результата**:
|
||||||
|
Убедитесь, что в папке `backend` появился файл `package.json`. В его первой строке должно быть указано `"type": "module"`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 **Урок 3: Установка фреймворка Express**
|
||||||
|
|
||||||
|
### **Цель урока**: Установить библиотеку Express — популярный фреймворк для создания веб-приложений и API на Node.js.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **Express** — это минималистичный и гибкий фреймворк, который значительно упрощает создание серверных приложений и маршрутов.
|
||||||
|
- **Зависимости (dependencies)** — это сторонние библиотеки (пакеты), которые использует ваш проект. Они управляются с помощью `npm` (Node Package Manager).
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
В папке `backend` выполните команду установки:
|
||||||
|
```bash
|
||||||
|
npm install express
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Что должно получиться**:
|
||||||
|
* В файле `package.json` в раздел `"dependencies"` добавится `"express"` с номером версии.
|
||||||
|
* В проекте появится папка `node_modules`, где хранятся все установленные библиотеки.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗑️ **Урок 4: Работа с `.gitignore` и первый коммит**
|
||||||
|
|
||||||
|
### **Цель урока**: Научиться игнорировать ненужные для репозитория файлы и зафиксировать изменения.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **`node_modules`** — это папка со всеми зависимостями проекта. Её **нельзя** добавлять в Git, так как она очень большая и её можно восстановить командой `npm install`.
|
||||||
|
- **`.gitignore`** — специальный файл, в котором перечисляются шаблоны файлов и папок, которые Git должен игнорировать.
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. **Создайте файл `.gitignore`** в корне вашего проекта (на одном уровне с папкой `backend`).
|
||||||
|
2. **Добавьте в него шаблоны**. Вы можете создать базовое содержимое на сайте [gitignore.io](https://www.toptal.com/developers/gitignore). Введите `Node, Windows, VisualStudioCode` и скопируйте сгенерированный текст в ваш файл.
|
||||||
|
3. **Убедитесь, что в `.gitignore` есть строки**:
|
||||||
|
```
|
||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
```
|
||||||
|
4. **Выполните коммит**:
|
||||||
|
```bash
|
||||||
|
# Вернитесь в корень проекта (если вы в папке backend)
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# Добавьте все новые файлы в staging area
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Зафиксируйте изменения с комментарием
|
||||||
|
git commit -m "feat: инициализирован проект Node.js с Express, добавлен .gitignore"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 **Урок 5: Создание базовой структуры сервера**
|
||||||
|
|
||||||
|
### **Цель урока**: Создать основные файлы приложения и понять их роль.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
Серверное приложение на Express обычно разделяют на несколько файлов для лучшей организации:
|
||||||
|
- **`server.js`** — точка входа. Запускает сервер, подключает основные настройки.
|
||||||
|
- **`app.js`** — ядро приложения. Содержит настройки Express и все маршруты (routes).
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. В папке `backend` создайте папку `src`.
|
||||||
|
2. Внутри `src` создайте два файла: `app.js` и `server.js`.
|
||||||
|
3. **В файл `app.js`** пока добавьте только создание экземпляра приложения:
|
||||||
|
```javascript
|
||||||
|
// backend/src/app.js
|
||||||
|
import express from 'express';
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
export default app; // Экспортируем app для использования в server.js
|
||||||
|
```
|
||||||
|
4. **В файл `server.js`** добавьте код запуска сервера:
|
||||||
|
```javascript
|
||||||
|
// backend/src/server.js
|
||||||
|
import app from './app.js';
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`Сервер запущен и слушает порт ${PORT}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Что должно получиться**:
|
||||||
|
Создана модульная структура приложения. Пока при запуске сервер будет работать, но на любой запрос возвращать ошибку `404`, так как маршруты не определены.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ▶️ **Урок 6: Первый запуск сервера**
|
||||||
|
|
||||||
|
### **Цель урока**: Запустить сервер и убедиться, что он работает, возвращая ожидаемую ошибку.
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. Из папки `backend` выполните команду:
|
||||||
|
```bash
|
||||||
|
node src/server.js
|
||||||
|
```
|
||||||
|
2. В консоли должно появиться сообщение: `Сервер запущен и слушает порт 3000`.
|
||||||
|
3. Откройте браузер и перейдите по адресу `http://localhost:3000`.
|
||||||
|
4. **Вы должны увидеть стандартную страницу ошибки `Cannot GET /`**. Это ожидаемо, так как мы не создали обработчик для корневого маршрута (`/`).
|
||||||
|
5. Остановите сервер, нажав `Ctrl + C` в терминале.
|
||||||
|
6. **Выполните коммит**:
|
||||||
|
```bash
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: создана базовая структура сервера, успешный запуск"
|
||||||
|
git push origin study # Или study-фамилия
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🖐️ **Урок 7: Создание первого маршрута (Hello World)**
|
||||||
|
|
||||||
|
### **Цель урока**: Создать простейший обработчик GET-запроса и получить ответ от сервера.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **Маршрут (route)** — это правило, которое определяет, как сервер будет реагировать на клиентский запрос к определенному URL (конечной точке) и HTTP-методу (GET, POST и т.д.).
|
||||||
|
- **Обработчик (handler)** — функция, которая принимает запрос (`req`) и формирует ответ (`res`).
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. Откройте файл `backend/src/app.js`.
|
||||||
|
2. **Добавьте обработчик для корневого маршрута (`/`) перед строкой `export default app;`**:
|
||||||
|
```javascript
|
||||||
|
// Обработчик GET-запроса на корневой URL '/'
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
// Устанавливаем заголовок ответа
|
||||||
|
res.setHeader('Content-Type', 'text/plain');
|
||||||
|
// Отправляем текстовый ответ
|
||||||
|
res.send('Hello World from my API!');
|
||||||
|
});
|
||||||
|
```
|
||||||
|
3. Запустите сервер снова (`node src/server.js`) и обновите страницу `http://localhost:3000` в браузере.
|
||||||
|
4. **Вы должны увидеть надпись `Hello World from my API!`**.
|
||||||
|
5. **Выполните коммит**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔢 **Урок 8: Работа с параметрами пути (Path Parameters)**
|
||||||
|
|
||||||
|
### **Цель урока**: Научиться создавать динамические маршруты и извлекать данные из URL.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **Статические маршруты** — это фиксированные адреса, например, `/about` или `/contacts`. Они всегда одинаковы.
|
||||||
|
- **Динамические маршруты** — это адреса, которые могут меняться. Например, страница профиля с разными именами пользователей: `/user/anna`, `/user/max`.
|
||||||
|
- **Параметры пути (Path Parameters)** — специальные части URL, которые меняются. В Express они обозначаются двоеточием (`:`), например: `/user/:username`.
|
||||||
|
- Когда кто-то заходит на `/user/anna`, Express видит `:username` в маршруте и понимает: "вместо `:username` подставлено `anna`". Это значение сохраняется в `req.params`.
|
||||||
|
|
||||||
|
### **Примеры разных параметров**:
|
||||||
|
|
||||||
|
1. **Один параметр**:
|
||||||
|
```javascript
|
||||||
|
// Когда заходят на /hello/Максим
|
||||||
|
app.get('/hello/:name', (req, res) => {
|
||||||
|
const name = req.params.name; // = "Максим"
|
||||||
|
res.send(`Привет, ${name}!`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Несколько параметров**:
|
||||||
|
```javascript
|
||||||
|
// Когда заходят на /book/сказки/5
|
||||||
|
app.get('/book/:genre/:page', (req, res) => {
|
||||||
|
const genre = req.params.genre; // = "сказки"
|
||||||
|
const page = req.params.page; // = "5"
|
||||||
|
res.send(`Жанр: ${genre}, Страница: ${page}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Параметр в середине пути**:
|
||||||
|
```javascript
|
||||||
|
// Когда заходят на /category/электроника/product/123
|
||||||
|
app.get('/category/:categoryName/product/:productId', (req, res) => {
|
||||||
|
const category = req.params.categoryName; // = "электроника"
|
||||||
|
const productId = req.params.productId; // = "123"
|
||||||
|
res.send(`Категория: ${category}, Товар: ${productId}`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Практические шаги**:
|
||||||
|
1. В файле `app.js` добавьте маршрут:
|
||||||
|
```javascript
|
||||||
|
// Пример запроса: GET http://localhost:3000/double/7
|
||||||
|
app.get('/double/:number', (req, res) => {
|
||||||
|
const input = req.params.number; // Получаем параметр из URL
|
||||||
|
|
||||||
|
// Проверяем, является ли параметр числом
|
||||||
|
if (!isNaN(input)) {
|
||||||
|
const number = parseFloat(input);
|
||||||
|
const result = number * 2;
|
||||||
|
res.send(`Если удвоить ${number}, получится ${result}`);
|
||||||
|
} else {
|
||||||
|
res.status(400).send('Пожалуйста, укажите число. Например: /double/10');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Протестируйте:
|
||||||
|
- `http://localhost:3000/double/7` → работает
|
||||||
|
- `http://localhost:3000/double/abc` → ошибка
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ➕➖✖️➗ **Урок 9: Практическое задание — Текстовый API-калькулятор**
|
||||||
|
|
||||||
|
### **Цель задания**: Создать простой калькулятор, который принимает числа в URL и возвращает текстовый результат.
|
||||||
|
|
||||||
|
### **Задание**:
|
||||||
|
Создайте 4 маршрута для основных математических операций. Формат ответа — обычный текст.
|
||||||
|
|
||||||
|
**Маршруты и примеры**:
|
||||||
|
1. **Сложение**: `GET /api/calc/sum/:a/:b`
|
||||||
|
- Пример: `GET /api/calc/sum/5/3`
|
||||||
|
- Ответ: `5 + 3 = 8`
|
||||||
|
|
||||||
|
2. **Вычитание**: `GET /api/calc/subtract/:a/:b`
|
||||||
|
- Пример: `GET /api/calc/subtract/10/4`
|
||||||
|
- Ответ: `10 - 4 = 6`
|
||||||
|
|
||||||
|
3. **Умножение**: `GET /api/calc/multiply/:a/:b`
|
||||||
|
- Пример: `GET /api/calc/multiply/7/2`
|
||||||
|
- Ответ: `7 * 2 = 14`
|
||||||
|
|
||||||
|
4. **Деление**: `GET /api/calc/divide/:a/:b`
|
||||||
|
- Пример: `GET /api/calc/divide/15/3`
|
||||||
|
- Ответ: `15 / 3 = 5`
|
||||||
|
|
||||||
|
### **Как это сделать**:
|
||||||
|
1. Для каждого маршрута получите параметры из `req.params.a` и `req.params.b`
|
||||||
|
2. Преобразуйте их в числа: `const num1 = parseFloat(req.params.a)`
|
||||||
|
3. Выполните операцию
|
||||||
|
4. Верните ответ в формате: ``res.send(`${num1} + ${num2} = ${result}`)``
|
||||||
|
|
||||||
|
### **Важно**:
|
||||||
|
- Пока не нужно проверять, корректные ли данные прислал пользователь
|
||||||
|
- Используйте шаблонные строки (обратные кавычки) для формирования ответа
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ **Урок 10: Базовые проверки в калькуляторе**
|
||||||
|
|
||||||
|
### **Цель урока**: Добавить минимальную проверку входных данных.
|
||||||
|
|
||||||
|
### **Задание**:
|
||||||
|
Доработайте калькулятор из урока 9, добавив две простые проверки:
|
||||||
|
|
||||||
|
1. **Проверка, что оба параметра — числа**
|
||||||
|
2. **Для деления — проверка, что второй параметр не ноль**
|
||||||
|
|
||||||
|
### **Как это сделать**:
|
||||||
|
|
||||||
|
**Шаг 1: Проверка на число**
|
||||||
|
В начале каждого обработчика добавьте:
|
||||||
|
```javascript
|
||||||
|
const a = parseFloat(req.params.a);
|
||||||
|
const b = parseFloat(req.params.b);
|
||||||
|
|
||||||
|
// Проверяем, являются ли оба параметра числами
|
||||||
|
if (isNaN(a) || isNaN(b)) {
|
||||||
|
return res.status(400).send('Ошибка: оба параметра должны быть числами');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Шаг 2: Проверка деления на ноль**
|
||||||
|
Только в обработчике деления добавьте после проверки на числа:
|
||||||
|
```javascript
|
||||||
|
// Проверка деления на ноль
|
||||||
|
if (b === 0) {
|
||||||
|
return res.status(400).send('Ошибка: на ноль делить нельзя');
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Что должно происходить**:
|
||||||
|
- `/api/calc/sum/5/3` → `5 + 3 = 8` (работает)
|
||||||
|
- `/api/calc/sum/5/abc` → `Ошибка: оба параметра должны быть числами` (ошибка 400)
|
||||||
|
- `/api/calc/divide/10/0` → `Ошибка: на ноль делить нельзя` (ошибка 400)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 **Урок 11: Введение в формат JSON**
|
||||||
|
|
||||||
|
### **Цель урока**: Понять, что такое JSON и научиться отправлять данные в этом формате.
|
||||||
|
|
||||||
|
### **Краткая теория**:
|
||||||
|
- **JSON (JavaScript Object Notation)** — популярный формат для обмена данными;
|
||||||
|
- у JSON есть строгий набор правил:
|
||||||
|
- Все ключи в двойных кавычках
|
||||||
|
- Значения: строки (в кавычках), числа, true/false, null, массивы [], объекты {}
|
||||||
|
- **Пример JSON**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"имя": "Иван",
|
||||||
|
"возраст": 16,
|
||||||
|
"хобби": ["программирование", "шахматы"],
|
||||||
|
"студент": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Практическое задание**:
|
||||||
|
1. Создайте маршрут `GET /api/user/:id`
|
||||||
|
2. Если `:id` — число, верните JSON с информацией о пользователе:
|
||||||
|
```javascript
|
||||||
|
app.get('/api/user/:id', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
|
||||||
|
if (!isNaN(id)) {
|
||||||
|
// Формируем вручную объект пользователя.
|
||||||
|
// Пока что просто притворимся, что мы загрузили его из базы данных.
|
||||||
|
const userData = {
|
||||||
|
userId: Number(id),
|
||||||
|
name: "Алексей Петров",
|
||||||
|
email: "alexey@example.com",
|
||||||
|
registered: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Отправляем как JSON
|
||||||
|
res.json(userData);
|
||||||
|
} else {
|
||||||
|
// Если id не число - ошибка в JSON формате
|
||||||
|
res.status(400).json({
|
||||||
|
error: "ID должен быть числом",
|
||||||
|
example: "/api/user/123"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
3. Протестируйте в браузере:
|
||||||
|
- `http://localhost:3000/api/user/123` → увидите красиво оформленный JSON
|
||||||
|
- `http://localhost:3000/api/user/abc` → JSON с ошибкой
|
||||||
|
|
||||||
|
### Обратите внимание
|
||||||
|
В примере мы возвращаем фальшивые данные. С настоящими динамическими данными (списки/объекты БД) мы поработаем позже.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 **Урок 12: Калькулятор с JSON-ответами**
|
||||||
|
|
||||||
|
### **Цель урока**: Переделать текстовый калькулятор для возврата JSON.
|
||||||
|
|
||||||
|
### **Задание**:
|
||||||
|
Измените все 4 операции калькулятора так, чтобы они возвращали данные в JSON-формате.
|
||||||
|
|
||||||
|
### **Формат успешного ответа**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"operation": "sum",
|
||||||
|
"arguments": {
|
||||||
|
"a": 5,
|
||||||
|
"b": 3
|
||||||
|
},
|
||||||
|
"result": 8
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Формат ответа с ошибкой**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"error": {
|
||||||
|
"code": "DIVISION_BY_ZERO",
|
||||||
|
"message": "Делитель не может быть равен нулю"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Как изменить код**:
|
||||||
|
|
||||||
|
1. **Заменяем `res.send()` на `res.json()`**
|
||||||
|
2. **Для успешного ответа** формируем объект:
|
||||||
|
```javascript
|
||||||
|
const response = {
|
||||||
|
success: true,
|
||||||
|
operation: "sum", // или "subtract", "multiply", "divide"
|
||||||
|
arguments: {
|
||||||
|
a: a,
|
||||||
|
b: b
|
||||||
|
},
|
||||||
|
result: a + b // здесь ваша операция
|
||||||
|
};
|
||||||
|
res.json(response);
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Для ошибок**:
|
||||||
|
```javascript
|
||||||
|
res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
error: {
|
||||||
|
code: "INVALID_NUMBERS", // или "DIVISION_BY_ZERO"
|
||||||
|
message: "Оба параметра должны быть числами"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Примеры кодов ошибок**:
|
||||||
|
- `"INVALID_NUMBERS"` — когда параметры не числа
|
||||||
|
- `"DIVISION_BY_ZERO"` — когда делим на ноль
|
||||||
Reference in New Issue
Block a user