为何jQuery when注释后数组内函数仍执行?求动态函数优化方案
你遇到的核心问题其实是函数调用时机的误解——你现在写的ajax1('1')是直接执行函数,而不是把函数逻辑延迟到$.when的时候才触发。
为什么注释掉$.when后函数依然执行?
当你写deferParams = [ajax1('1'), ajax1('2')]的时候,JavaScript引擎会先执行这两个ajax1调用,把它们的返回值(也就是$.ajax生成的Deferred对象)塞进数组里。这一步和后面的$.when代码完全独立,不管你有没有写$.when,这两个AJAX请求都会在数组创建的瞬间发起。$.when的作用只是等待这些已经发起的请求全部完成,而不是触发请求本身。
更好的处理方案
根据你的需求,分两种情况调整:
场景1:希望请求立刻发起,只需要等待全部完成
如果你的需求就是要马上发起这些AJAX请求,只是需要在它们都结束后执行后续逻辑,那当前的代码逻辑其实是对的,只是注意修正一个拼写错误:$.when.apply($, deferparams)里的deferparams应该是deferParams(大小写不一致)。
不过可以简化一下数组的创建逻辑,让代码更简洁:
function multiAjaxCalls() { var numOfAjaxToCall = 2; // 生成对应数量的Deferred对象 var deferParams = Array.from({length: numOfAjaxToCall}, (_, i) => ajax1(String(i+1))); $.when.apply($, deferParams).then( function () { console.log("所有AJAX请求已完成,可以合并数据了。"); var objects = arguments; console.log(objects); }, function (event) { console.log("请求失败:", event); } ); // 剩余的ajax1、ajax2、ajaxCommon函数保持不变 }
场景2:希望在$.when执行时才发起请求
如果你的需求是只有当准备好等待请求完成时,才发起这些AJAX请求,那需要把函数包装成“延迟执行”的形式,比如存储函数引用,而不是直接调用:
function multiAjaxCalls() { var numOfAjaxToCall = 2; // 存储返回Deferred对象的函数,而不是直接调用 var requestFns = []; if (numOfAjaxToCall === 1) { requestFns = [() => ajax1('1')]; } else if (numOfAjaxToCall === 2) { requestFns = [() => ajax1('1'), () => ajax1('2')]; } // 只有到这里才会发起请求 var deferParams = requestFns.map(fn => fn()); $.when.apply($, deferParams).then( function () { console.log("所有AJAX请求已完成,可以合并数据了。"); var objects = arguments; console.log(objects); }, function (event) { console.log("请求失败:", event); } ); // 剩余的ajax1、ajax2、ajaxCommon函数保持不变 }
这样一来,当你注释掉$.when相关的代码时,requestFns.map(...)不会执行,AJAX请求也就不会发起了。
额外小提示
$.ajax返回的Deferred对象本身就已经包含了done和fail的状态,你不需要在ajaxCommon里额外用.done()和.fail()包裹——因为$.when会监听这些Deferred的完成/失败状态,直接返回$.ajax(...)即可:
function ajaxCommon(siteURL) { console.log("开始请求:", siteURL); return $.ajax({ url: siteURL, method: 'GET' }); }
后续的成功/失败逻辑统一放在$.when的.then()里处理就行,这样代码更简洁。
内容的提问来源于stack exchange,提问作者Rezzy

