如何延迟3个AJAX调用中的指定请求,使其在其余请求完成后执行
问题原因
你原来的实现存在三个核心问题:
- 逻辑错位:你将
setTimeout写在了overalleff.php请求的success回调中,等于先发起了目标请求,等请求返回后才执行延时,完全不符合「等前两个请求完成再发起第三个请求」的需求 - 固定延时不可靠:AJAX是异步网络请求,响应速度受网络波动、接口负载影响极大,固定2秒延时既可能出现前两个请求还未返回就执行了后续逻辑,也可能出现请求早已完成白白等待的情况
- 无效代码:你写在延时回调里的
$data没有任何执行逻辑,不会产生任何作用
解决方案
jQuery的AJAX请求默认返回Deferred对象,可以用$.when()方法监听多个异步请求的完成状态,等所有请求都成功返回后再执行后续逻辑,是实现异步依赖的标准方案。
步骤1:修改两个前置请求函数,返回Deferred对象
需要先让cbutton(对应pickingeff.php请求)和abutton(对应packingeff.php请求)返回请求的Deferred对象,方便后续判断完成状态:
var barray = []; function cbutton() { $('input:radio[name="cheking"]:checked').val(); const varies = $("#fromdate").val(); const varies2 = $("#todate").val(); if (varies === "" || varies2 === "") { alert("Please fill in all 2 fields first and then submit again"); // 表单校验失败返回拒绝状态的Deferred return $.Deferred().reject("pickingeff表单校验失败"); } barray.push(`${varies}~${varies2}`); // 返回AJAX请求的Deferred对象 return $.ajax({ type: "POST", url: "pickingeff.php", data: { fromdate: varies, todate: varies2 } }); } var sarray = []; function abutton() { const varies3 = $("#fromdate").val(); const varies4 = $("#todate").val(); if (varies3 === "" || varies4 === "") { alert("Please fill in all 2 fields first and then submit again"); return $.Deferred().reject("packingeff表单校验失败"); } sarray.push(`${varies3}~${varies4}`); $('#loadingmessage').show(); // 返回AJAX请求的Deferred对象 return $.ajax({ type: "POST", url: "packingeff.php", data: { fromdate: varies3, todate: varies4 } }).done(() => { $('#loadingmessage').hide(); }); }
步骤2:修改pbutton逻辑,等待前置请求完成后再发起目标请求
根据你的触发场景二选一即可:
场景A:点击pbutton时同时触发两个前置请求,等都完成再请求overalleff.php
function pbutton() { // 同时发起两个前置请求 const pickingReq = cbutton(); const packingReq = abutton(); // 等待两个请求都成功完成 $.when(pickingReq, packingReq).done((pickingRes, packingRes) => { // pickingRes是pickingeff.php的返回结果,packingRes是packingeff.php的返回结果 // 此处可先做你需要的前置计算 $.ajax({ url: "overalleff.php", success: (data) => { // 处理overalleff.php的返回结果 console.log("总效率请求完成", data); } }); }).fail((err) => { // 任意一个前置请求校验失败或网络失败都会进入此处 console.error("前置请求异常", err); }); }
场景B:用户分别点击两个按钮触发前置请求,两个都完成后自动触发目标请求
新增状态标记判断两个请求的完成状态:
// 新增两个请求完成状态标记 let pickingDone = false; let packingDone = false; // 修改cbutton的done回调,更新状态并检查是否可以触发目标请求 function cbutton() { // ... 原有逻辑不变,仅修改AJAX的done回调 return $.ajax({/*原有参数*/}).done(() => { pickingDone = true; checkAndRunOverall(); }); } // 修改abutton的done回调,更新状态并检查是否可以触发目标请求 function abutton() { // ... 原有逻辑不变,仅修改AJAX的done回调 return $.ajax({/*原有参数*/}).done((msg) => { $('#loadingmessage').hide(); packingDone = true; checkAndRunOverall(); }); } // 检查两个请求是否都完成,都完成则发起目标请求 function checkAndRunOverall() { if (pickingDone && packingDone) { $.ajax({ url: "overalleff.php", success: (data) => { // 处理返回结果 } }); // 重置标记避免重复触发 pickingDone = false; packingDone = false; } }
内容的提问来源于stack exchange,提问作者user16982570
相关产品推荐
相关产品推荐

