Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Асинхронные обработчики

Многие операции на сервере асинхронные: чтение файла, запрос к базе данных или к другому сайту. Обработчик маршрута может быть async-функцией и ждать результат через await. В Express 5 ошибка внутри такой функции сама попадает в обработчик ошибок — оборачивать код в try...catch не обязательно.

Асинхронный маршрут

Пусть текст страницы «О блоге» хранится в файле content/about.txt в корне проекта. Прочитаем его в контроллере:

// src/controllers/pagesController.js
import { readFile } from 'node:fs/promises';
 
export async function about(req, res) {
  const text = await readFile('content/about.txt', 'utf8');
  res.send(`<h1>О блоге</h1><p>${text}</p>`);
}

И подключим маршрут в src/app.js:

// src/app.js
import * as pagesController from './controllers/pagesController.js';
 
app.get('/about', pagesController.about);

По адресу /about появится текст из файла. Пока файл читается, сервер не стоит на месте и обслуживает другие запросы.

Что происходит при ошибке

Удалите или переименуйте content/about.txt и снова откройте /about. readFile() вернёт отклонённый промис, а Express 5 заметит это и вызовет обработчик ошибок из прошлого урока. Посетитель увидит «Ошибка сервера», в терминале появится ENOENT: no such file or directory.

Как было в Express 4

В старых проектах можно встретить такую обёртку:

// src/controllers/pagesController.js
export async function about(req, res, next) {
  try {
    const text = await readFile('content/about.txt', 'utf8');
    res.send(`<p>${text}</p>`);
  } catch (error) {
    next(error);
  }
}

Express 4 не следил за промисами, и без try...catch ошибка оставалась необработанной. В Express 5 этот код по-прежнему работает, но писать его не нужно.

Когда try...catch всё же нужен

try...catch пишут, когда ошибку нужно не передать дальше, а обработать на месте — например, показать запасной текст:

// src/controllers/pagesController.js
export async function about(req, res) {
  let text = 'Скоро здесь будет рассказ о блоге.';
 
  try {
    text = await readFile('content/about.txt', 'utf8');
  } catch {
    // файла нет — оставляем текст по умолчанию
  }
 
  res.send(`<h1>О блоге</h1><p>${text}</p>`);
}

Теперь без файла страница всё равно откроется со строкой «Скоро здесь будет рассказ о блоге».

Частая ошибка

Express 5 видит только тот промис, который вернул сам обработчик. Если забыть await, функция закончится раньше, чем операция, и ошибка выйдет «мимо» Express: процесс напишет Unhandled promise rejection и может завершиться. Ставьте await перед каждой асинхронной операцией, результат или ошибка которой важны для ответа.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.