如何让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
相关产品推荐
相关产品推荐

