You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:46:40