> Как реализовать взаимодействие фронтенда и бэкенда для генерации тяжелого отчета без таймаута (Python)
Уровень: senior · Роль: backend · Язык: Python · Категория: Технические вопросы
Компании: JEDai
Стек: Python
> Пример ответа
Для генерации тяжелого отчета без таймаута используем асинхронный подход с очередью задач. Основная идея: клиент отправляет запрос на создание отчета, бэкенд ставит задачу в очередь (например, через Celery или RQ), а фронтенд периодически опрашивает статус через отдельный эндпоинт.
Пример реализации на Python с Celery и Redis:
- Бэкенд (Flask + Celery):
PYTHONfrom flask import Flask, request, jsonifyfrom celery import Celeryapp = Flask(__name__)celery = Celery(app.name, broker='redis://localhost:6379/0')@celery.task(bind=True, max_retries=3)def generate_report(self, params):# Тяжелая генерация отчетаreport_data = long_running_computation(params)return {'status': 'completed', 'data': report_data}@app.route('/api/report', methods=['POST'])def create_report():task = generate_report.delay(request.json)return jsonify({'task_id': task.id}), 202@app.route('/api/report/<task_id>', methods=['GET'])def get_report_status(task_id):task = generate_report.AsyncResult(task_id)if task.state == 'PENDING':response = {'status': 'pending'}elif task.state == 'FAILURE':response = {'status': 'failed', 'error': str(task.info)}elif task.state == 'SUCCESS':response = {'status': 'completed', 'data': task.result}return jsonify(response)
- Фронтенд (JavaScript):
JAVASCRIPTasync function generateReport(params) {const response = await fetch('/api/report', {method: 'POST',body: JSON.stringify(params)});const { task_id } = await response.json();// Polling каждые 2 секундыwhile (true) {const statusResponse = await fetch(`/api/report/${task_id}`);const result = await statusResponse.json();if (result.status === 'completed') {displayReport(result.data);break;} else if (result.status === 'failed') {showError(result.error);break;}await new Promise(resolve => setTimeout(resolve, 2000));}}
Дополнительные оптимизации:
- Используйте WebSocket вместо polling для реального времени
- Сохраняйте готовый отчет в S3/локальное хранилище и отдавайте ссылку
- Установите разумный TTL для задач в Celery (например,
result_expires=3600) - Для очень больших отчетов используйте стриминг через
StreamingResponseв Flask
Этот подход гарантирует отсутствие таймаута, так как HTTP-запросы короткие, а тяжелая работа выполняется в фоне.
> Похожие задачи по Python
> Похожие задачи по backend
Приходилось ли оптимизировать алгоритм, а не только архитектуру
Каково мнение о коренной статической типизации
Какие технологии и стеки вам интересны
Как организовано тестирование в команде
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью