如何按顺序执行指定jQuery函数?附相关实现代码
让包含异步操作的函数按顺序执行的解决方案
问题背景
你当前的代码里,直接依次调用fn_one到fn_four,但这些函数内部的$('#search-city-form').trigger('click')大概率触发了异步操作(比如AJAX表单提交),所以四个函数会几乎同时执行,根本不会按你想要的顺序等待前一个完成再执行下一个。要解决这个问题,我们需要把每个函数改造成能异步等待完成的形式,然后按顺序调用。
具体实现步骤
1. 把每个函数包装成Promise
首先,我们需要让每个函数返回一个Promise,这样就能监听它内部的异步操作什么时候完成。这里分两种情况处理:
情况A:你能控制表单提交的AJAX代码
如果表单的点击事件是你自己写的AJAX,那最好在AJAX的成功回调里触发一个自定义事件,比如searchCompleted,这样我们就能精准监听操作完成:
// 先修改原来的表单点击事件(如果是你自己写的) $('#search-city-form').on('click', function() { $.ajax({ url: '/你的搜索接口地址', data: $(this).closest('form').serialize(), success: function(data) { // 这里处理返回的数据 $(document).trigger('searchCompleted'); // 触发完成事件 }, error: function() { $(document).trigger('searchCompleted'); // 出错也可以触发,或者单独处理错误 } }); }); // 然后改造四个函数,让它们返回Promise function fn_one() { return new Promise((resolve) => { $('#search-city-form').trigger('click'); // 监听一次完成事件,完成后resolve $(document).one('searchCompleted', resolve); }); } function fn_two() { return new Promise((resolve) => { $("form input[name='tariffId']").val("137"); $('#search-city-form').trigger('click'); $(document).one('searchCompleted', resolve); }); } function fn_three() { return new Promise((resolve) => { $("form input[name='tariffId']").val("138"); $('#search-city-form').trigger('click'); $(document).one('searchCompleted', resolve); }); } function fn_four() { return new Promise((resolve) => { $("form input[name='tariffId']").val("139"); $('#search-city-form').trigger('click'); $(document).one('searchCompleted', resolve); }); }
情况B:无法控制表单的AJAX代码(比如第三方组件)
如果表单提交是第三方组件的逻辑,你没法修改,那可以用jQuery的全局ajaxComplete事件,同时判断请求的URL来确保是我们要等的那个请求:
function fn_one() { return new Promise((resolve) => { $('#search-city-form').trigger('click'); // 监听一次AJAX完成,并且判断URL是目标接口 $(document).one('ajaxComplete', function(event, xhr, settings) { if (settings.url === '/你的搜索接口地址') { resolve(); } }); }); } // fn_two、fn_three、fn_four同理修改,逻辑和上面一致
2. 按顺序执行函数
现在我们有了返回Promise的函数,就可以用async/await或者Promise链式调用来保证顺序:
方式一:用async/await(更直观)
$(document).on('click','.ui-menu li', async function(){ try { await fn_one(); // 等fn_one完成 await fn_two(); // 等fn_two完成 await fn_three(); // 等fn_three完成 await fn_four(); // 最后执行fn_four } catch (err) { console.error('执行过程中出错:', err); } });
方式二:用Promise链式调用(兼容旧环境)
如果你的项目环境不支持async/await,也可以用链式then:
$(document).on('click','.ui-menu li', function(){ fn_one() .then(() => fn_two()) .then(() => fn_three()) .then(() => fn_four()) .catch(err => console.error('执行出错:', err)); });
为什么这样能解决问题?
原来的代码里,四个函数是同步执行的,不管内部的异步操作有没有完成,都会立刻执行下一个。而用Promise包装后,await或者then会等待前一个Promise的resolve信号(也就是异步操作完成),才会继续执行下一个函数,这样就严格保证了顺序。
内容的提问来源于stack exchange,提问作者kulan
相关产品推荐
相关产品推荐

