如何在Ajax中使用jQuery $.each()?实现串行SMS发送与结果处理
问题根源:$.each同步执行,Ajax异步无等待
你猜的没错!jQuery的$.each是同步遍历,它会一口气把循环里的代码全部执行完——包括发起所有的Ajax请求,但这些请求都是异步的,不会阻塞循环继续跑。所以你的i计数逻辑在循环执行的瞬间就完成了,这时候所有短信请求可能还在半路上,自然"Klar!"会提前显示,而且你也没法保证短信发送和DOM追加的顺序和接收者列表一致。
方案1:递归串行处理(兼容旧浏览器)
我们可以把接收者转成数组,然后写一个递归函数,每次只处理一个接收者,等这个Ajax请求成功(或失败)后,再处理下一个,直到全部完成。这样就能严格保证顺序,并且在最后一个处理完后显示完成提示。
修改后的代码:
// 把recipients对象转成[{nr: xxx, name: xxx}]的数组,方便按顺序处理 const recipientList = Object.entries(recipients).map(([nr, name]) => ({ nr, name })); let currentIndex = 0; const total = recipientList.length; function sendNextSMS() { if (currentIndex >= total) { // 所有处理完成 $('#send_sms_btn').removeClass('disabled').text('Skicka'); $('<span class="text-success">Klar!</span><br>').appendTo('#recipients'); return; } const { nr, name } = recipientList[currentIndex]; $.ajax({ url: 'php/sms_send.php', method: 'POST', data: { nr: nr, name: name, text: text }, success: function(result){ // 输出当前请求的状态 $('<span>'+result+'</span><br>').appendTo('#recipients'); // 处理完当前的,继续下一个 currentIndex++; sendNextSMS(); }, error: function(err){ // 即使出错,也可以选择继续下一个,或者在这里处理错误逻辑 console.log(err); currentIndex++; sendNextSMS(); } }); } // 启动发送流程 sendNextSMS();
方案2:用async/await实现串行(现代环境推荐)
如果你项目的运行环境支持ES6+(大部分现代浏览器都支持),用async/await会更简洁,代码逻辑更清晰。因为jQuery的$.ajax返回的jqXHR对象本身就兼容Promise,所以我们可以直接用await等待每个请求完成。
修改后的代码:
async function sendAllSMS() { const recipientList = Object.entries(recipients).map(([nr, name]) => ({ nr, name })); try { for (const { nr, name } of recipientList) { // 等待当前Ajax请求完成 const result = await $.ajax({ url: 'php/sms_send.php', method: 'POST', data: { nr: nr, name: name, text: text } }); // 请求成功后追加DOM $('<span>'+result+'</span><br>').appendTo('#recipients'); } } catch (err) { console.log('某条短信发送失败:', err); } finally { // 不管全部成功还是有失败,最后都更新按钮状态和提示 $('#send_sms_btn').removeClass('disabled').text('Skicka'); $('<span class="text-success">Klar!</span><br>').appendTo('#recipients'); } } // 启动发送 sendAllSMS();
为什么你的原代码计数失效?
再回头看你的原代码:
$.each瞬间遍历完所有接收者,i会在极短时间内从1递增到count,所以count === i的判断会在所有Ajax请求发起后立刻触发,导致"Klar!"提前显示,而不是等所有请求完成。- 因为Ajax是异步的,各个请求的返回顺序不一定和遍历顺序一致,DOM追加的内容顺序可能会乱。
内容的提问来源于stack exchange,提问作者Björn C
相关产品推荐
相关产品推荐

