КейсыРастИИшка
Приложения для бизнеса

Долгий расчёт на сайте: статус задачи вместо бесконечного спиннера

Обсудить задачу → Оставить заявку

Пользователь запускает долгий расчёт, закрывает вкладку и теряет результат, потому что интерфейс показывал только спиннер. Нужно разложить операцию на состояния с идентификатором и честно показывать, где она сейчас.

Долгий расчёт показывают через идентификатор задачи и явные состояния: принято, в очереди, обработка, готово, частичный результат, ошибка, истекло. Проценты допустимы только при измеримой модели прогресса, иначе показывают этапы. Идентификатор переживает закрытие вкладки и потерю сети, а повторный запуск защищают ключом идемпотентности.

В условном сценарии менеджер небольшой оптовой компании загружает на сайт прайс из 18 000 позиций и просит пересчитать матрицу скидок по трём каналам. Расчёт идёт на сервере, вкладка открыта, спиннер вращается. Через минуту менеджер переключается на звонок, закрывает вкладку, а вернувшись, видит пустую форму и не понимает, сохранился ли результат.

Долгая операция ломает привычную схему «запрос — ответ». Браузер не держит соединение бесконечно, человек не держит внимание на спиннере, а сервер не обязан помнить, кто именно ждал ответа. Поэтому задачу приходится разложить на состояния: запрос принят, поставлен в очередь, обрабатывается, готов, выдан или истёк. Каждое состояние — отдельный факт с идентификатором, и интерфейс показывает не «крутится», а «где мы сейчас».

Общий маршрут долгого расчёта от приёма до выдачи
Общий маршрут долгого расчёта от приёма до выдачи. Авторская схема 404ai.

Идентификатор расчёта как единственный якорь

Первый шаг — перестать считать, что ответ придёт в тот же HTTP-запрос, который его запустил. Сервер при приёме задачи возвращает короткое подтверждение и идентификатор расчёта. Дальше клиент спрашивает по этому идентификатору статус, а не ждёт у моря погоды. Это ровно тот приём, который Microsoft описывает как asynchronous request-reply pattern: принять, дать ссылку на состояние, опрашивать или уведомить, отдать результат.

Идентификатор — не косметика. Он переживает перезагрузку страницы, смену устройства и потерю сети. Если менеджер закрыл вкладку, расчёт не обязан умирать: он привязан к идентификатору, а не к открытому окну. При следующем входе интерфейс спрашивает «что у меня в работе» и восстанавливает картину. Без такого якоря любая долгая операция превращается в лотерею: угадай, успело или нет.

Важно сразу договориться, чем идентификатор не является. Это не сессия пользователя и не токен доступа. Это ссылка на конкретную задачу с её параметрами, статусом и сроком жизни. Права на просмотр результата проверяются отдельно, иначе чужой идентификатор станет пропуском к чужим данным.

Если ваша задача — показать состояние долгого расчёта, на странице соответствующего направления 404ai можно посмотреть опубликованные возможности и оставить описание текущего процесса. Конкретные подключения, исходные данные и критерии приёмки согласуем отдельно.

Очередь, обработка и готовность — три разных факта

Соблазн свести всё к «в процессе» велик, но он скрывает разные ситуации. В очереди задача ждёт свободного обработчика, и это может длиться долго при пиковой нагрузке. В обработке она уже считается, и здесь появляется шанс показать осмысленный прогресс. Готовность означает, что результат посчитан и лежит на хранении. Смешав эти состояния, интерфейс врёт пользователю: он показывает бодрый прогресс там, где на самом деле ещё ничего не началось.

Разделение помогает и поддержке. Когда менеджер звонит с вопросом «почему так долго», оператор по идентификатору видит, что задача стоит в очереди двадцать минут из-за наплыва загрузок, а не «зависла». Это разговор о факте, а не о догадке. И это же разделение задаёт честные ожидания: если очередь длинная, лучше сказать «в очереди, ориентировочно столько-то», чем рисовать фальшивые проценты.

Отдельно стоит готовность к выдаче. Результат может быть посчитан, но ещё не выгружен в нужный формат или не проверен на целостность. Между «готово» и «можно скачать» иногда есть шаг, который тоже надо показать, иначе пользователь нажмёт кнопку и получит ошибку.

Рабочий объект задачи: параметры, статус, срок жизни
Рабочий объект задачи: параметры, статус, срок жизни. Авторская схема 404ai.

Что показывать, когда процент неизмерим

Не у каждой задачи есть честная шкала. Пересчёт матрицы скидок по фиксированному числу комбинаций можно считать по шагам: обработано 4 000 из 18 000. А вот операция, где заранее неизвестно, сколько данных придётся перебрать, процентов не имеет. Рисовать «67%» на такой задаче — значит выдумывать число, которое ни на чём не основано.

Здесь выручает смена модели прогресса. Вместо доли от целого показывают этапы: «проверка данных», «расчёт по каналам», «сборка результата». Это не точнее в процентах, зато честнее. Пользователь видит, что работа движется, и примерно понимает, на каком она свете. Для доступности индикатор можно размечать ролью ARIA progressbar. Измеримый прогресс получает корректное aria-valuenow, а у неопределённого прогресса это значение не задают. Название этапа и существенные изменения состояния должны быть доступны текстом, без выдуманного процента.

Правило простое: процент показываем только при определённой модели прогресса, где известно общее количество шагов и оно не меняется по ходу. Во всех остальных случаях — этапы и текст. Это избавляет от классической проблемы, когда полоска замирает на 90% и висит там десять минут.

Возврат к результату после закрытой вкладки

Самый частый провал — не технический сбой, а человеческое поведение. Менеджер запустил расчёт, ушёл на встречу, вернулся и не помнит, где искать. Если результат живёт только в памяти вкладки, он потерян. Если у задачи есть идентификатор и список «мои расчёты», картина восстанавливается за пару секунд.

Условный пример: расчёт запущен в 10:14, вкладка закрыта в 10:16, менеджер вернулся в 11:40. В списке задач он видит запись «матрица скидок, три канала, запущено 10:14, готово 10:19, срок хранения до 17:40». Он открывает результат, сверяет и продолжает работу. Никаких повторных запусков и никакой надежды на память.

Список задач — это не архив на века. У каждого результата есть срок жизни, и это нормально. Хранить всё вечно дорого и рискованно, поэтому интерфейс заранее говорит, до какого момента результат доступен, и предлагает перезапустить, если срок истёк. Честное «истёк, запустить заново» лучше, чем битая ссылка без объяснений.

Проверка исключений: закрытая вкладка, сеть, повтор
Проверка исключений: закрытая вкладка, сеть, повтор. Авторская схема 404ai.

Сеть пропала: что переживает клиент, а что сервер

Потеря связи на стороне пользователя не должна означать потерю задачи. Сервер уже принял запрос и работает по своему расписанию. Клиент в этот момент теряет возможность опрашивать статус, но не саму задачу. Когда связь вернулась, интерфейс снова спрашивает по идентификатору и получает актуальное состояние — возможно, уже «готово».

Опасность в другом: интерфейс, не получив ответа, решает, что запрос не дошёл, и отправляет его повторно. Так появляется двойной расчёт. Защита здесь — идемпотентность на приёме: повторный запрос с тем же ключом идемпотентности не создаёт новую задачу, а возвращает существующую. Ключ генерируется на клиенте один раз при запуске конкретной задачи и переиспользуется только при повторах именно этого запуска; для новой задачи с другими параметрами генерируется новый ключ.

Отмена — отдельная история. Кнопка «отменить» останавливает ожидание на клиенте, но не обязана останавливать работу на сервере. Если задача уже в обработке, её отмена — это отдельный запрос, который сервер может принять или отклонить. AbortController аккуратно закрывает клиентское ожидание, но не является командой «останови расчёт». Путать эти вещи опасно: пользователь думает, что отменил, а результат всё равно появляется.

Двойной запуск и цена лишней работы

Двойной запрос — не редкость: двойной клик, повтор после таймаута, две вкладки с одной формой. Без защиты каждый такой случай порождает лишнюю нагрузку и путаницу в результатах. Идемпотентный приём решает проблему на входе, но нужен и на выходе: список задач должен показывать одну запись, а не три одинаковых.

Полезно ввести понятие активной задачи. Если по тем же параметрам уже идёт расчёт, интерфейс предлагает подождать его, а не запускать новый. Это экономит ресурсы и избавляет от ситуации, когда два почти одинаковых результата приходят с разницей в секунды, и непонятно, какой из них актуальный.

При этом не стоит превращать защиту в запрет. Иногда пользователю действительно нужен пересчёт с другими параметрами, и это законная новая задача. Различие простое: тот же ключ идемпотентности — та же задача; новый ключ — новая. Интерфейс должен это различать, а не блокировать всё подряд.

Частичный результат: когда готово не всё

Бывает, что расчёт по двум каналам завершён, а третий упал из-за некорректных данных. Показывать «ошибка» на всю задачу — значит терять уже сделанную работу. Показывать «готово» — значит скрывать проблему. Правильный ответ — частичный результат с явной пометкой, какие части посчитаны, а какие нет, и почему.

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

В интерфейсе частичный результат стоит показывать отдельным состоянием, а не прятать за общим «готово». Пользователь должен видеть, что именно он получил, прежде чем начнёт на это опираться.

Приёмочные тесты состояний долгого расчёта
Приёмочные тесты состояний долгого расчёта. Авторская схема 404ai.

Состояние долгого расчёта на экране сотрудника

Спиннер сообщает только одно: «что-то происходит». Для долгой задачи этого мало. Рабочий экран должен отвечать на три вопроса: что за задача, на каком она этапе, что можно сделать прямо сейчас. Ответы меняются по мере продвижения, и интерфейс обязан меняться вместе с ними.

Состояние Что видит сотрудник Доступное действие
Принято «Задача принята, номер такой-то» Закрыть вкладку, вернуться позже
В очереди «Ждёт обработки, впереди N задач» Отменить ожидание
Обработка Этапы или процент, если измерим Смотреть, не закрывать принудительно
Готово «Результат готов, доступен до такого-то» Открыть, скачать, перезапустить
Частично «Посчитано 2 из 3 частей» Забрать готовое, дозапустить остальное
Ошибка «Не удалось: причина» Исправить данные, повторить
Истекло «Срок хранения прошёл» Запустить заново

Такая таблица — не украшение, а контракт между бэкендом и фронтендом. Каждое состояние должно быть явно представлено в API, иначе интерфейс начнёт додумывать. А додумывание в долгих операциях почти всегда заканчивается неверным сообщением.

Полезно добавить историю переходов: когда задача принята, когда началась обработка, когда завершилась. Это помогает и сотруднику, и поддержке. История — это факты, а не догадки, и на неё можно опереться в разговоре.

Состояние долгого расчёта: исключения и проверка условий

Первое исключение — задача, которая никогда не завершится. Обработчик упал, очередь потеряла запись, внешний сервис молчит. Нужен таймаут на уровне задачи: если за отведённое время статус не сменился, задача помечается как зависшая, и сотрудник видит это явно. Молчаливое «в обработке» сутками — худший из вариантов.

Второе — изменение параметров на лету. Пользователь запустил расчёт, потом решил поменять входные данные. Это не правка текущей задачи, а новая задача с новым идентификатором. Старая продолжает считаться по прежним параметрам, и результат по ним остаётся валидным для того набора данных. Смешивать нельзя.

Третье — права доступа, которые изменились, пока задача считалась. Сотрудник переведён в другой отдел, и доступ к результату должен проверяться на момент выдачи, а не на момент запуска. Иначе получится, что уволенный сотрудник забирает результат по старой ссылке.

Четвёртое — результат, который стал неактуален. Данные в системе поменялись, а расчёт сделан по старым. Это не ошибка расчёта, а вопрос актуальности, и интерфейс должен честно показывать, на каких данных построен результат и когда они были зафиксированы.

Практикум: расчёт доставки по 40 регионам
Практикум: расчёт доставки по 40 регионам. Авторская схема 404ai.

Прогон расчёта после перезагрузки и истечения хранения

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

Сценарий Ожидаемое поведение Что проверяем
Закрыл вкладку во время расчёта Задача продолжается, результат доступен в списке Идентификатор переживает сессию
Пропала сеть на минуту После восстановления статус актуален Опрос возобновляется, задача не дублируется
Двойной клик по кнопке Одна задача, один результат Ключ идемпотентности работает
Один канал упал Частичный результат с пометкой Дробление на подзадачи
Истёк срок хранения Явное сообщение и предложение перезапуска Честность вместо битой ссылки
Отмена во время обработки Ожидание закрыто, сервер решает отдельно Разделение клиентской и серверной отмены

Эти сценарии стоит превратить в автотесты на уровне API и ручные проверки на уровне интерфейса. Отдельно проверяют доступность: скринридер должен корректно читать состояния, а не только визуальную полоску. И отдельно — поведение при медленной сети, потому что именно там вылезают гонки между опросом статуса и повторным запуском.

Практикум: расчёт стоимости доставки по 40 регионам

Возьмём другой пример, чтобы не повторять матрицу скидок. Условная логистическая компания считает стоимость доставки по 40 регионам с учётом веса, габаритов и сезонных коэффициентов. Расчёт занимает от десяти секунд до нескольких минут в зависимости от объёма справочников.

Шаг первый — приём. Клиент отправляет параметры с ключом идемпотентности и получает идентификатор. Шаг второй — опрос статуса с разумным интервалом, например раз в несколько секунд, с постепенным замедлением, чтобы не забивать сервер. Шаг третий — выдача результата по идентификатору с проверкой прав. Шаг четвёртый — хранение с явным сроком и понятным сообщением при истечении.

Прогресс здесь измерим: 40 регионов — это 40 шагов, и доля посчитанных регионов даёт честный процент. Если какой-то регион не удалось посчитать из-за отсутствия справочника, он попадает в частичный результат с причиной. Сотрудник забирает 37 готовых регионов и отдельно разбирается с тремя.

Проверка на этом примере простая: закрыть вкладку на середине, вернуться через полчаса, убедиться, что результат на месте и помечен сроком хранения. Затем запустить тот же расчёт дважды подряд и убедиться, что появилась одна задача, а не две. Затем оборвать сеть на этапе опроса и проверить, что после восстановления статус подтянулся, а расчёт не задвоился.

Один шаг, который стоит сделать первым

Прежде чем рисовать прогресс-бары, стоит завести идентификатор задачи и список состояний. Это скучная часть, но именно она решает исходную проблему: пользователь обновил страницу и всё-таки узнал результат. Проценты, этапы и красивые полоски — надстройка над этим фундаментом, и без него они только маскируют потерю задачи.

Конкретный шаг проверки: возьмите одну свою долгую операцию и пройдите по ней сценарий «закрыл вкладку — вернулся через час». Если результат находится, схема уже работает. Если нет — начинать надо с идентификатора и состояний, а не с анимации спиннера.

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

Представим условный расчёт, который пользователь начал на ноутбуке, а результат открыл с телефона. Если задача существует только в памяти первой вкладки, второе устройство ничего о ней не узнает. Для восстанавливаемого просмотра нужен серверный идентификатор задания, привязка к допустимому пользователю и проверка доступа при каждом запросе состояния. Один факт знания адреса результата не должен автоматически давать право видеть данные расчёта.

На втором устройстве интерфейс загружает подтверждённое состояние, а не продолжает старый визуальный процент. После завершения он показывает версию входных данных, время расчёта и сам результат либо понятную причину, почему результат пока недоступен. Если исходные данные уже изменились, это видно отдельно: старый завершённый расчёт не становится актуальным только от повторного открытия страницы.

В приёмочном прогоне закройте первую вкладку, дождитесь завершения работы и откройте разрешённый маршрут заново. Затем повторите проверку без нужных прав. Первый случай должен восстанавливать доступное состояние, второй — корректно отказывать без раскрытия результата. Это требования к проектированию приложения; серверные задания, хранение результатов и проверку полномочий нужно реализовать и проверить отдельно.

Смежный вопрос разобран отдельно: Push-уведомления в приложении: сообщение должно дожить до смысла.

Источники и границы разбора

Источники и статус проверки на 9 ноября 2026. Первичные документы поясняют указанные механизмы; доступность и границы каждого источника отмечены ниже. Методические рекомендации и условные примеры составляют самостоятельную часть разбора.

  1. Приложения для бизнеса

    Опубликованное направление работы 404ai. Предлагаемая в статье методика не означает, что каждое описанное действие уже доступно без настройки; состав решения согласуется отдельно.

  2. Microsoft: Asynchronous request-reply pattern

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

  3. MDN: ARIA progressbar role

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

  4. MDN: AbortController

    Первичная документация указанного инструмента или механизма. Практические рекомендации и условные эпизоды статьи — самостоятельная методика, а не описание готовых функций 404ai.

Частые вопросы

Зачем долгому расчёту отдельный идентификатор задачи?

Идентификатор связывает результат с конкретной задачей, а не с открытой вкладкой. Он переживает перезагрузку страницы, смену устройства и потерю сети, поэтому пользователь может вернуться и узнать состояние. Права на просмотр результата проверяют отдельно при каждом запросе, иначе чужой идентификатор станет пропуском к чужим данным.

Когда на экране можно показывать процент выполнения?

Процент показывают только при определённой модели прогресса, где известно общее число шагов и оно не меняется по ходу. Если заранее неизвестно, сколько данных придётся перебрать, вместо процентов показывают этапы и текст. Выдуманное число вроде 67% на неизмеримой задаче вводит пользователя в заблуждение и замирает на одном месте.

Что делать, если сеть пропала во время опроса статуса?

Сервер уже принял задачу и продолжает работу по своему расписанию, клиент теряет только возможность опрашивать статус. После восстановления связи интерфейс снова спрашивает по идентификатору и получает актуальное состояние, возможно уже готовое. Повторную отправку защищают ключом идемпотентности, чтобы не появился двойной расчёт.

Как показывать результат, если часть расчёта завершилась ошибкой?

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

Что происходит с результатом после истечения срока хранения?

Срок доступности результата задают заранее и показывают пользователю. После его истечения интерфейс объясняет причину недоступности и предлагает новый расчёт, если это разрешено процессом. Повторный запуск использует актуальные исходные данные и является новой задачей. Старый завершённый расчёт нельзя обозначать ошибкой только потому, что его сохранённый результат уже удалён.

404ai · задача вашей компании

Обсудим вашу задачу

Расскажите, какой результат нужен вашей компании и как задача решается сейчас. Уточним исходные данные, ограничения и подходящий формат работы. Состав работ, условия и сроки согласуем после оценки.

Укажите телефон или Telegram для ответа

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

Заявка принята. Свяжемся, уточним задачу и согласуем следующий шаг.

Можно также написать напрямую: Telegram 404ai.

Подробнее: Приложения для бизнеса
Разбор задачи — бесплатноОтвет за 15 минут
Разобрать задачу