Django应用间歇性出现Failed To Fetch Error问题求助
解决Django应用中JS间歇性
failed to fetch错误的建议 1. 解决Django开发服务器的并发瓶颈
Django默认的runserver是单线程服务,当请求调用耗时较长的GRPC第三方API时,新请求会被阻塞,甚至引发连接拒绝(服务器无法及时响应新请求)。
- 改用多线程/多进程开发服务器:
启动时开启多线程模式:
或者用生产级服务器测试本地环境,比如gunicorn:python manage.py runserver --threaded
这样能同时处理多个请求,避免长耗时API阻塞导致的连接问题。gunicorn your_project.wsgi:application --workers 4 --threads 2 --bind 127.0.0.1:8000
2. 异步处理第三方GRPC API调用
ThirdPartyApi.spin()耗时过长会占用当前请求的线程/进程,导致服务器无法响应其他请求,甚至触发超时断开连接。
用Celery异步执行任务(推荐):
先封装Celery任务:# tasks.py from celery import shared_task from .models import Spin @shared_task def call_third_party_api(user_id, spin_id): spin = Spin.objects.get(id=spin_id) try: ThirdPartyApi.spin(user_id, spin) except Exception as e: # 记录错误或更新spin状态 print(f"API调用失败: {str(e)}")然后修改视图,触发任务后立即返回响应:
# 视图中 spin.save() # 触发异步任务,不阻塞当前请求 call_third_party_api.delay(request.user.id, spin.id) # 立即返回成功响应 return JsonResponse({'status': 'success', 'message': '请求已提交,正在处理'})或用Django异步视图简化处理(适合Django3.1+):
import asyncio from django.utils.decorators import sync_to_async @login_required(login_url='login') async def create(request): if request.method == "POST": # 同步代码用sync_to_async包装 form = await sync_to_async(SpinForm)(request.POST) is_valid = await sync_to_async(form.is_valid)() if is_valid: # ... 省略数据保存代码 # 异步执行GRPC调用,不阻塞线程 try: await asyncio.to_thread(ThirdPartyApi.spin, request.user, spin) except Exception as e: return JsonResponse({'status': 'failed', 'message': str(e)}) return JsonResponse({'status': 'success', 'spin': 'win'})
3. 为fetch请求添加超时控制
浏览器默认的fetch超时限制可能导致长耗时请求被主动断开,出现空响应或连接拒绝。
- 在JS代码中添加超时控制:
const controller = new AbortController(); // 设置30秒超时,可根据实际调整 const timeoutId = setTimeout(() => controller.abort(), 30000); fetch(data.getAttribute('action'), { method: data.getAttribute('method'), body: new FormData(data), headers:{ "X-CSRFToken": csrf_token, "X-Requested-With": "XMLHttpRequest"}, signal: controller.signal }).then(res=>res.json()) .then(function (data) { clearTimeout(timeoutId); // 原后续处理逻辑 document.getElementById('create-submit-button').style.border = "2px solid #ebebeb" if(data.status == 'success'){ console.log('happy path') } else { Swal.fire({ icon: 'error', title: 'there was an issue with your request', text: data.message, }) } }) .catch(error => { clearTimeout(timeoutId); if (error.name === 'AbortError') { Swal.fire({ icon: 'error', title: '请求超时', text: '服务器处理耗时过长,请稍后重试' }); } else { console.log('Error: ', error) } })
4. 完善Django日志排查隐藏错误
当前Django日志无相关记录,可能是日志配置未捕获到异常,需调整配置:
- 修改
settings.py中的日志配置:import os LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'root': { 'handlers': ['console'], 'level': 'DEBUG', }, 'loggers': { 'django': { 'handlers': ['console'], 'level': os.getenv('DJANGO_LOG_LEVEL', 'DEBUG'), 'propagate': False, }, }, } - 在视图外层添加全局异常捕获:
@login_required(login_url='login') def create(request): try: # 原视图所有代码 except Exception as e: import logging logger = logging.getLogger(__name__) logger.error(f"视图处理异常: {str(e)}", exc_info=True) return JsonResponse({ 'status': 'failed', 'message': '服务器内部错误' })
5. 排查本地环境问题
- 清除浏览器缓存,禁用缓存插件,避免缓存导致的异常请求。
- 检查本地防火墙、代理软件,确保
localhost:8000的连接未被间歇性拦截。
内容的提问来源于stack exchange,提问作者HectorOfTroy407
相关产品推荐
相关产品推荐

