You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django应用间歇性出现Failed To Fetch Error问题求助

解决Django应用中JS间歇性failed to fetch错误的建议

1. 解决Django开发服务器的并发瓶颈

Django默认的runserver是单线程服务,当请求调用耗时较长的GRPC第三方API时,新请求会被阻塞,甚至引发连接拒绝(服务器无法及时响应新请求)。

  • 改用多线程/多进程开发服务器:
    启动时开启多线程模式:
    python manage.py runserver --threaded
    
    或者用生产级服务器测试本地环境,比如gunicorn:
    gunicorn your_project.wsgi:application --workers 4 --threads 2 --bind 127.0.0.1:8000
    
    这样能同时处理多个请求,避免长耗时API阻塞导致的连接问题。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:35:45