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

如何让AJAX函数仅在后端Django脚本运行时执行?

实现仅在后端脚本运行时触发AJAX请求

完全可行,你可以通过前端本地值对比或后端返回状态标识两种方式实现,以下是具体方案:

方案一:前端本地判断值是否停止变化

通过记录上一次获取的数值,每次请求回来后对比,若连续多次无变化则终止AJAX请求(设置连续次数阈值避免网络波动误判)。

修改后的JavaScript代码:

var interval = 1000;
var lastPoints = null;
var noChangeCount = 0;
var maxNoChangeCount = 3; // 允许连续3次无变化,可根据需求调整

function update() {
    $.ajax({
        type: 'GET',
        url: 'http://localhost:8000/api/updating',
        headers: {'Authorization': "Token " + token},
        dataType: 'json',
        success: function (data) {
            $('#points_a').html(data);
            
            // 对比当前值与上一次值
            if (data === lastPoints) {
                noChangeCount++;
                // 连续无变化达到阈值,停止后续请求
                if (noChangeCount >= maxNoChangeCount) {
                    console.log('数值已停止更新,终止AJAX请求');
                    return;
                }
            } else {
                // 值有变化,重置计数并更新记录值
                noChangeCount = 0;
                lastPoints = data;
            }
        },
        complete: function () {
            // 仅当未达到停止条件时,调度下一次请求
            if (noChangeCount < maxNoChangeCount) {
                setTimeout(update, interval);
            }
        }
    });
}

// 初始化第一次请求
setTimeout(update, interval);

方案二:后端返回更新状态(更可靠)

前端判断存在误判风险(比如后端脚本异常终止但数值刚好停在某个值),更可靠的方式是让后端接口返回一个状态字段,告知前端当前脚本是否仍在运行。

步骤1:修改Django后端接口与任务函数

首先用缓存(如Redis)记录任务运行状态(当前递归+time.sleep的任务方式在生产环境极易出问题,建议改用Celery等任务队列管理定时任务):

from django.http import JsonResponse
import redis
import time
from .models import Wallet

# 初始化Redis连接
r = redis.Redis(host='localhost', port=6379, db=0)

def updating_api(request):
    userid = request.user.id  # 从请求中获取当前用户ID
    # 查询用户的任务是否在运行
    is_updating = r.exists(f"user_updating:{userid}")
    
    # 获取当前用户的积分
    wallet = Wallet.objects.filter(name__id=userid).first()
    points = wallet.points if wallet else 0
    
    return JsonResponse({
        'points': points,
        'is_updating': is_updating
    })

# 修改后的任务函数
def task(userid, seconds_for_thirtydays=0):
    # 标记任务正在运行
    r.set(f"user_updating:{userid}", "1")
    try:
        if seconds_for_thirtydays < 2592000:
            wallet = Wallet.objects.filter(name__id=userid).first()
            wallet.points += 1
            wallet.save()
            
            seconds_for_thirtydays += 1
            time.sleep(1)
            task(userid, seconds_for_thirtydays)
    finally:
        # 任务结束或异常时清除状态标记
        r.delete(f"user_updating:{userid}")

步骤2:修改前端AJAX逻辑

根据后端返回的is_updating字段决定是否继续请求:

var interval = 1000;

function update() {
    $.ajax({
        type: 'GET',
        url: 'http://localhost:8000/api/updating',
        headers: {'Authorization': "Token " + token},
        dataType: 'json',
        success: function (response) {
            $('#points_a').html(response.points);
            
            // 后端告知已停止更新,终止请求
            if (!response.is_updating) {
                console.log('后端脚本已停止运行,终止AJAX请求');
                return;
            }
        },
        complete: function (xhr) {
            // 仅当后端返回仍在更新时,调度下一次请求
            if (xhr.responseJSON?.is_updating) {
                setTimeout(update, interval);
            }
        }
    });
}

setTimeout(update, interval);

注意事项

你当前使用的递归+time.sleep实现后端定时任务的方式存在严重问题:递归深度超过Python默认栈限制(默认约1000)会直接崩溃,且长时间占用线程会导致服务无法处理其他请求。生产环境强烈建议使用Celery+Redis/RabbitMQ实现异步定时任务,便于管理任务状态与生命周期。

内容的提问来源于stack exchange,提问作者Fors1t

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:05:24