如何确保同一事件的两个独立回调按顺序执行(含异步操作)
问题解答
你没有误解$.Deferred()的工作原理,原方案确实存在后续事件触发时的逻辑漏洞。
原方案的问题
原方案使用全局变量存储Deferred实例,每次触发function1都会覆盖这个变量:
- 若短时间内多次触发事件,前一次的AJAX还未完成,后一次触发会替换全局
Deferred,导致前一次的function2错误监听后一次的异步状态; - 若某次触发时,
function2执行前全局Deferred已经处于resolved状态(比如上一次触发遗留的),function2会立即执行,无法等待当前function1的AJAX完成。
解决方案:基于事件对象的独立Deferred
利用jQuery事件回调共享同一事件对象的特性,为每次事件触发创建独立的Deferred并存储在事件对象中,让function2监听当前触发对应的异步状态:
function function1(e) { // 为当前事件触发创建独立的Deferred,绑定到事件对象上 e.function1Deferred = $.Deferred(); $.ajax({ url: 'your-url', method: 'GET', success: function(data) { console.log("Function1 AJAX请求完成"); e.function1Deferred.resolve(data); // 异步完成后resolve }, error: function(xhr) { console.log("Function1 AJAX请求失败"); e.function1Deferred.reject(xhr); // 异步失败后reject } }); } function function2(e) { // 从事件对象中获取当前触发对应的Deferred if (e.function1Deferred) { e.function1Deferred .done(function(data) { console.log("Function2在function1完成后执行", data); }) .fail(function(xhr) { // 可选:处理function1异步失败的场景 console.log("Function1执行失败,Function2可在此处理异常", xhr); }); } } // 保留独立的on绑定 $('body').on('change', '#my-div', function1); $('body').on('change', '#my-div', function2);
原理说明
- jQuery触发事件时,会为当前事件生成唯一的事件对象,所有绑定的回调函数都会收到这个对象;
function1在执行时,为当前事件创建专属的Deferred并挂载到事件对象上;function2从同一事件对象中获取这个Deferred,确保监听的是当前触发的function1的异步状态,完全隔离不同事件触发的上下文。
内容的提问来源于stack exchange,提问作者rosecabbagedragon
相关产品推荐
相关产品推荐

