Короткий ответ: Node.js-сервер не должен “рисовать” ошибку для Backbone напрямую. Сервер должен вернуть корректный HTTP-статус и JSON с понятным текстом ошибки, а Backbone должен поймать ошибку в error-callback и отрисовать сообщение во View
Backbone — старая, но еще встречающаяся связка в проектах. Главная путаница здесь в слове “рендерить”: Express отвечает за HTTP-ответ, а Backbone отвечает за отображение в браузере. Если смешать эти роли, код быстро превращается в набор частных костылей
Какой формат ошибки отдавать с Node.js
Для API удобен единый формат
{
"message": "Название обязательно",
"fields": {
"name": "Введите название"
}
}
message — общий текст ошибки, fields — ошибки конкретных полей формы. Такой JSON удобно показать в Backbone View
Express-роут с ошибкой валидации
Пример сервера
const express = require("express");
const app = express();
app.use(express.json());
app.post("/api/tasks", (req, res) => {
const { title } = req.body;
if (!title || title.trim() === "") {
res.status(422).json({
message: "Задачу нельзя сохранить",
fields: {
title: "Введите название задачи"
}
});
return;
}
res.status(201).json({
id: Date.now(),
title
});
});
app.listen(3000, () => {
console.log("Server started");
});
Статус 422 подходит для ошибки валидации. Для неизвестной серверной ошибки используйте 500, для отсутствующей записи — 404, для запрета доступа — 403
Middleware для серверных ошибок
Если ошибка произошла глубже в коде, ее лучше обрабатывать централизованно
app.use((error, req, res, next) => {
console.error(error);
res.status(500).json({
message: "Внутренняя ошибка сервера"
});
});
Не отдавайте пользователю stack trace, SQL-запросы, токены и внутренние детали. В логах это может быть полезно, в браузере — нет
Backbone Model
Модель может быть простой
const Task = Backbone.Model.extend({
urlRoot: "/api/tasks"
});
При сохранении Backbone отправит данные на сервер
const task = new Task({
title: ""
});
Если сервер вернет 422, Backbone вызовет обработчик ошибки
Backbone View с отображением ошибок
Пример View
const TaskFormView = Backbone.View.extend({
el: "#task-form",
events: {
"submit": "onSubmit"
},
onSubmit(event) {
event.preventDefault();
const title = this.$("[name=title]").val();
const task = new Task({ title });
this.clearErrors();
task.save(null, {
success: () => {
this.$(".result").text("Задача сохранена");
},
error: (model, xhr) => {
const response = xhr.responseJSON || {};
this.renderErrors(response);
}
});
},
renderErrors(error) {
this.$(".form-error").text(error.message || "Не удалось сохранить данные");
if (error.fields && error.fields.title) {
this.$(".title-error").text(error.fields.title);
}
},
clearErrors() {
this.$(".form-error").text("");
this.$(".title-error").text("");
this.$(".result").text("");
}
});
HTML может выглядеть так
<form id="task-form">
<div class="form-error"></div>
<label>
Название
<input name="title" type="text">
</label>
<div class="title-error"></div>
<button type="submit">Сохранить</button>
<div class="result"></div>
</form>
Теперь ошибка приходит с Node.js, но рендерится на стороне Backbone
Почему не стоит возвращать готовый HTML ошибки
Сервер может вернуть
<div class="error">Введите название</div>
Но для Backbone-приложения это обычно хуже, чем JSON. Клиенту сложнее управлять состоянием формы, подсветкой полей и повторным рендером. JSON дает клиенту данные, а View решает, как именно их показать
Исключение — если проект изначально серверный и Backbone используется только для маленьких интерактивных блоков. Тогда можно отдавать HTML-фрагменты, но это уже другая архитектура
Как обработать ошибку fetch
Для загрузки данных принцип такой же
collection.fetch({
success: () => {
view.render();
},
error: (collection, xhr) => {
const response = xhr.responseJSON || {};
view.renderError(response.message || "Не удалось загрузить данные");
}
});
Сервер должен вернуть нормальный статус и JSON
app.get("/api/tasks", (req, res) => {
res.status(500).json({
message: "Не удалось загрузить задачи"
});
});
Мини-практика
Сделайте форму с одним полем title. На сервере верните 422, если поле пустое. В Backbone View покажите общий текст ошибки над формой и отдельный текст под полем. Затем добавьте успешный сценарий и очищайте ошибки перед новой отправкой
Так вы сразу увидите правильное разделение: Express проверяет данные, Backbone показывает результат пользователю
Частые ошибки
Сервер возвращает 200 даже при ошибке Backbone не попадет в error-callback, если HTTP-статус успешный. Для ошибки валидации используйте 422
Клиент ждет responseJSON, а сервер отдает текст Возвращайте res.json(...), чтобы Backbone мог прочитать xhr.responseJSON
Показывают внутреннюю ошибку пользователю Пользователю нужен понятный текст, разработчику — подробный лог на сервере
Рисуют ошибку в нескольких местах без очистки Перед новой отправкой формы очищайте старые сообщения, иначе интерфейс будет показывать устаревшие ошибки
Что почитать дальше по Node.js
Если нужен общий маршрут по теме, откройте рубрику Node.js. Для соседних задач пригодятся эти разборы:
- Как правильно настроить маршрут в Node.js, Express и Mongoose
- Node.js + MongoDB: первая коллекция из приложения
- Node.js + MySQL: REST API для первых данных
- Node.js LTS: какую версию ставить новичку



