Не вдається знайти модуль: налагодження імпортів Express та параметрів маршруту
API погоди TypeScript Express не працює через відсутній імпорт контролера. Перевірте шляхи, регістри та експорти, а потім перевірте значення :city перед викликом API актуальної погоди.
Відлагодження API погоди на TypeScript Express часто допомагає краще зрозуміти, як взаємодіють компоненти серверного бекенду Node, ніж будь-який інший абстрактний огляд REST.
Помилка
Після того, як проект було розділено на маршрути та контролери, сервер припинив працювати з такою помилкою:
Cannot find module '../controllers/weatherController'
Це повідомлення є поширеним, коли бекенд складається з кількох файлів. Express імпортує weatherController, але система не може знайти шлях до цього модуля.
Що перевірити
Слідуйте певній послідовності для усунення проблеми, замість того щоб вгадувати.
Чи існує файл? У директорії src/ мають бути наступні елементи:
src/
├── controllers/
│ └── weatherController.ts
Чи точно збігається назва папки? Краще використовувати controllers, а не controller чи Controllers. На файлових системах з різкою чутливістю до регістру важливі як множина, так і регістр назв.
Чи збігається назва файлу точно? Очікуйте weatherController.ts, а не WeatherController.ts, weathercontroller.ts чи weather-controller.ts. Механізм розрішення модулів TypeScript вважає їх різними об’єктами.
Чи правильний шлях імпорту? У файлі weatherRoutes.ts імпорти та підключення маршрутів виглядають так:
import { Router } from "express";
import { getWeather } from "../controllers/weatherController";
const router = Router();router.get("/:city", getWeather);export default router;
Чи справді контролер експортує функцію? Часто трапляється, що обробник функції пишеться без export, тож імпорт маршруту не має на що підключитися.
import { Request, Response } from "express";
export const getWeather = (req: Request, res: Response): void => {
const { city } = req.params; res.json({
city,
temperature: 29,
condition: "Cloudy",
humidity: 82,
});
};
Додавання export перед getWeather відновило роботу сервера. Одне ключове слово — одна усунута помилка.
Що вже охоплює проект
На цьому етапі сервіс прогнозування погоди вже містить кілька елементів, характерних для продакшну:
- Інструментальний комплекс TypeScript для репозиторію
- Процес Express HTTP у режимі роботи
- Окремі каталоги замість одного величезного файлу
- Маршрутизатори URL, підключені до обробників
- Модулі-обробники для логіки запитів
- Параметри шляху, такі як
:city - Структуровані дані у форматі JSON
- Виправлення проблеми відсутнього модуля шляхом перевірки шляхів та експортів локально
Розуміння параметрів маршрутів
Спробуйте використати цей маршрут через HTTP-клієнта, такого як Postman:
GET http://localhost:3000/weather/bangalore
GET http://localhost:3000/weather/mumbai
GET http://localhost:3000/weather/chennai
Кожна відповідь змінює поле city. Структура залишається стабільною: temperature, condition та humidity залишаються присутніми. Рядок з назвою міста надходить з сегмента шляху після /weather/ та доступний як req.params.city. Саме для цього існують параметри маршруту: одне визначення маршруту, але кілька значень можуть бути підставлені за кожним запитом.
Наступна задача: базова перевірка
Запит, схожий на наведений нижче, все ще успішно обробляється з фейковими даними:
GET /weather/123
і повертає щось на кшталт:
{
"city": "123",
"temperature": 29,
"condition": "Cloudy",
"humidity": 82
}
Назва міста не повинна складатися лише з цифр. Такі випадки слід відхилити, а не розглядати як коректний вхідні дані про погоду.
Перевірте параметр міста за допомогою регулярного виразу /^\d+$/. У разі повної відповідності поверніть код 400 Bad Request, а не фейкові дані про погоду:
res.status(400).json({
error: "City name must contain letters.",
});
Інакше поверніть звичайний пакет даних про погоду. Впровадження перевірки перед пошуком готової відповіді дозволяє краще дотримуватися правил, ніж просто вставляти готовий фрагмент.
Швидка перевірка знань
Короткий тест допомагає підтвердити розуміння теми, а не просто забезпечити безпроблемну компіляцію:
1. Яка різниця між GET /weather/:city та GET /weather?city=bangalore? Сегменти шляху використовують обов’язкові параметри маршруту, вбудовані у шаблон URL. Значення після ? є параметрами запиту та залишаються необов’язковими. Використовуйте параметри маршруту, коли значення визначає ресурс; параметри запиту — для фільтрів та перемикачів.
2. Чому використовувати res.status(400).json() замість просто res.json()? Однією лише функцією res.json() за замовчуванням встановлюється статус 200 OK. Для недійсних даних потрібен статус, який вказує на невдачу, а не лише рядок з помилкою у тілі. Клієнти покладаються саме на цей код.
3. Який шар відповідає за бізнес-правила — роутер, контролер чи щось інше? Правила слід розміщувати у контролерах. Роутери лише пов’язують метод HTTP та шлях із обробником. Валідація та зовнішні виклики спочатку знаходяться у контролері, а потім переходять до модуля сервісу у міру зростання додатку.
4. Що містить req.params.city для запиту GET /weather/mumbai? Рядок "mumbai", точно такий, як він введений у шляху.
Що буде далі
Штучне погодне середовище виконало свою функцію. Наступним етапом є використання API реальної погоди, що передбачає:
- Звернення до зовнішнього HTTP API
- Змінні середовища (
.env), щоб ключі ніколи не були закодовані безпосередньо у коді - Використання
fetchабоaxiosдля надсилання запитів - Чітке керування таймаутами та проблемами на стороні сервера
- Папку з сервісами, щоб контролери не виконували роботу HTTP-клієнта
Шлях запиту отримує ще один рівень:
Browser/Postman
│
▼
Routes
│
▼
Controllers
│
▼
Services
│
▼
Weather API (external)
Така ієрархічна структура характерна для багатьох продакшн-додатків на Express. Поступове її створення забезпечує чітку точку відката у разі збою під час інтеграції з реальними даними, замість того щоб збирати всі проблеми в один файл.