Gernar
Frontend DeveloperHTTP, API и сеть

Интервью-вопрос

Чем POST отличается от DELETE

Коротко: POST отправляет данные для создания или команды, DELETE удаляет конкретный ресурс. На собеседовании важно не забыть про идемпотентность, 204 и обновление UI.

Добавлен
Редакция

Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.

🐰0
🥚0

Мини-квиз

Проверка перед разбором

Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.

Вопрос 1 из 60 правильно

Как коротко объяснить разницу между POST и DELETE?

Выберите ответ, который лучше звучит на интервью.

Варианты ответа

Разбор

Разобраться, а не зазубрить

Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.

Базовая идея

POST можно читать как: "сервер, возьми эти данные и выполни действие". Часто результатом будет новый пользователь, заказ или комментарий. Но POST используют и там, где нет чистого CRUD: отправить письмо, запустить импорт, пересчитать отчет.

DELETE звучит конкретнее: "удали вот этот ресурс". Поэтому хороший адрес обычно сам показывает цель удаления: DELETE /users/123, DELETE /todos/42.

Как это выглядит в API

У POST и DELETE разный контракт между фронтендом и бэкендом. Отличается не только метод, но и место для данных, ожидаемый статус, обработка ошибок и следующий шаг в интерфейсе.

POST /users
Content-Type: application/json

{ "name": "John", "email": "john@example.com" }

Нормальный ответ на создание:

201 Created
Location: /users/123

Удаление того же пользователя обычно выглядит так:

DELETE /users/123

ID не нужно прятать в body. URL уже говорит, какой ресурс удаляется.

Как выбрать метод

1Нужно только прочитать данные?
GET или HEAD, не POST и не DELETE
2Нужно создать объект, а ID выдаст сервер?
POST /users с телом запроса
3Нужно удалить уже известный объект?
DELETE /users/123
4Нужно выполнить команду, а не обычный CRUD?
POST /reports/rebuild или POST /imports

Самая частая ловушка: повтор запроса

Идемпотентность означает простую вещь: один и тот же запрос можно повторить, и итоговое состояние будет таким же, как после одного выполнения.

С обычным POST это не гарантируется:

POST /orders
Content-Type: application/json

{ "productId": 10, "count": 1 }

Если пользователь дважды нажмет кнопку или retry-механизм повторит запрос, сервер может создать два заказа. Для платежей и заказов это больно, поэтому в таких API часто вводят Idempotency-Key или другую защиту от дублей.

У DELETE другая семантика:

DELETE /orders/42

После первого запроса заказа 42 нет. После второго его тоже нет. Сервер может ответить уже не 204, а 404, но он не должен из-за повтора удалить что-то еще.

Что важно для фронтенда

Статусы, о которых стоит помнить

POST201 / 200 / 202

Ресурс создан, команда выполнена или задача поставлена в очередь.

DELETE204 / 200

Удаление прошло успешно. При 204 в ответе нет body.

POST400 / 422

Сервер не принял данные. Обычно нужно показать ошибки формы.

DELETE404 / 409

Объект уже не найден или сервер не может удалить его сейчас.

POST и DELETE401 / 403

Пользователь не авторизован или у него нет прав на действие.

POST
  1. 1Взять данные из формы или собрать параметры команды.
  2. 2Отправить body с правильным Content-Type на адрес коллекции или операции.
  3. 3После успеха показать созданный объект, добавить его в список или перейти на новую страницу.
DELETE
  1. 1Определить ID объекта и, если удаление опасное, попросить подтверждение.
  2. 2Отправить запрос на URL конкретного ресурса, обычно без обязательного body.
  3. 3После успеха убрать объект из UI, сбросить кэш или заново запросить список.

Пример POST с явной проверкой статуса:

type UserPayload = {
  name: string;
  email: string;
};

const createUser = async (payload: UserPayload) => {
  const response = await fetch("/api/users", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });

  if (response.status !== 201) {
    throw new Error("Пользователя не удалось создать");
  }

  return response.json();
};

Пример DELETE, где успешный ответ может быть пустым:

const deleteUser = async (userId: string) => {
  const response = await fetch(`/api/users/${userId}`, {
    method: "DELETE",
  });

  if (response.status === 204) {
    return;
  }

  if (response.status === 404) {
    throw new Error("Пользователь уже удален или не найден");
  }

  if (!response.ok) {
    throw new Error("Пользователя не удалось удалить");
  }
};

Здесь легко ошибиться и вызвать response.json() после 204 No Content. Тела у такого ответа нет, значит парсить нечего.

После успешного DELETE экран должен перестать показывать удаленный объект. Обычно хватает одного из трех действий: убрать элемент из локального состояния, инвалидировать кэш запроса или заново получить список.

С optimistic UI лучше не геройствовать. Можно сразу убрать карточку, чтобы интерфейс казался быстрым. Но если сервер вернет 403, 404, 409 или случится сетевая ошибка, карточку надо вернуть и показать нормальное сообщение.

Нестандартные случаи

В реальных проектах встречается POST /users/123/delete. Иногда это наследие старого API, ограничение шлюза, HTML-форма без поддержки DELETE или просто договоренность команды. Это не катастрофа, но если вы проектируете REST API с нуля, DELETE /users/123 читается лучше.

DELETE описывает намерение клиента, а не физическую операцию в базе. Бэкенд может удалить строку, поставить deletedAt, сменить статус на archived или скрыть объект из выдачи. Для клиента это все равно удаление, и внешний контракт может оставаться DELETE /users/123.

POST и DELETE меняют состояние сервера. Если авторизация держится на cookie, для таких запросов обычно нужна CSRF-защита. И еще раз: DELETE не становится safe только потому, что он идемпотентен. Safe означает "не меняет состояние", а удаление состояние меняет.

Частые ошибки

Где обычно ошибаются

Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.

  1. 1

    Сводить POST только к созданию

    POST часто создает ресурс, но этим дело не заканчивается. Им же запускают импорт, отправку письма, пересчет отчета, подтверждение платежа. На интервью лучше сказать: создание ресурса или запуск серверной операции.
  2. 2

    Называть DELETE безопасным

    DELETE идемпотентен, но не safe. Он меняет состояние сервера. Safe-method не должен ничего менять, поэтому классические примеры здесь: GET и HEAD.
  3. 3

    Ждать одинаковый ответ при идемпотентности

    Идемпотентность смотрит на итоговое состояние, а не на один и тот же статус. Первый DELETE может вернуть 204, второй404, но ресурс уже удален в обоих случаях.
  4. 4

    Делать body обязательным для DELETE

    Удаляемый ресурс обычно указывают в URL, напримерDELETE /users/123. Body у DELETE возможен, но как основной контракт он хуже читается и хуже поддерживается инструментами.
  5. 5

    Парсить JSON после 204 No Content

    У 204 нет тела. Если вызвать response.json(), код упадет на парсинге пустой строки. Такой статус нужно обработать отдельной веткой.
  6. 6

    Забывать откат optimistic UI

    Если карточку сразу убрали со страницы, при ошибке ее надо вернуть. Иначе интерфейс показывает одно, а сервер хранит другое, и пользователь потом не понимает, кому верить.
  7. 7

    Сваливать 409 Conflict в общую ошибку

    409 часто означает не технический сбой, а конфликт состояния: например, объект связан с другими данными и его нельзя удалить. Для такого случая нужен отдельный текст, а не сухое "что-то пошло не так".

Follow-up

Что могут спросить дальше

Короткие ответы на вопросы, которыми интервьюер часто проверяет, что вы правда понимаете разницу между методами.

Живые ответы

Видео с похожим вопросом

Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.

Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.

Содержание