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

Ajax回调返回[object object]求助:循环内Ajax获取表格数据

解决循环中异步AJAX获取数据组装HTML的问题

兄弟,你遇到的核心问题就是AJAX的异步特性——你的同步循环代码会在AJAX请求完成前就执行,这时候getData()返回的根本不是你想要的td字符串,而是jQuery的AJAX请求对象(也就是你看到的[Object object]);而success回调里的结果要等服务器响应后才会生成,这时候你的循环早就跑完了,自然拿不到正确值。

问题拆解

  1. $.ajax()本身返回的是jqXHR对象(实现了Promise接口),不是success回调里的返回值,直接把它加到html里肯定会显示对象。
  2. 循环是同步执行的,而每个AJAX请求是异步完成的,你没法在循环里同步拿到回调里的结果——回调触发的时候,当前循环的迭代早就结束了。
  3. 你代码里用了var i,这还会导致闭包问题:所有AJAX请求最终拿到的i都是循环的最后一个值,这也是隐藏的坑。

解决方案:用async/await处理异步请求

现在最直观的方式是用async/await让异步代码看起来像同步的,同时并行处理所有请求保证效率:

// 封装单个日期的请求与td生成逻辑
async function getDayTd(i) {
  try {
    // 用await等待AJAX请求完成,直接拿到返回数据
    const data = await $.ajax({
      url: "http://localhost:8888/vs-time-tracking-ajax-calendar/",
      data: { i: i },
      type: "POST",
      dataType: "json"
    });

    // 生成对应的td元素
    let tdClass = "ic__day";
    const targetDate = moment(timeNowLocal).date(data.i).format("D.M.YYYY");
    if (targetDate === timeNow.format("D.M.YYYY")) {
      tdClass = "ic__day ic__day_state_current";
    } else if (timeSelected && targetDate === timeSelected.format("D.M.YYYY")) {
      tdClass = "ic__day ic__day_state_selected";
    }
    return `<td class="${tdClass}">${data.i}</td>`;
  } catch (error) {
    alert(error.responseText);
    // 出错时返回一个容错的td,避免影响整体结构
    return `<td class="ic__day ic__day_state_error">Error</td>`;
  }
}

// 批量处理所有日期请求,组装最终HTML
async function buildCalendarHtml() {
  let html = "";
  // 收集所有请求的Promise对象
  const tdPromises = [];
  // 用let i避免闭包问题
  for (let i = 1; i <= monthLastDay; i++) {
    tdPromises.push(getDayTd(i));
  }

  // 等待所有请求完成,一次性拿到所有生成好的td字符串
  const tdElements = await Promise.all(tdPromises);
  // 拼接所有td
  html += tdElements.join("");

  // 这里就可以用生成好的html做后续操作了,比如插入到DOM
  console.log(html);
  // 示例:$("#calendar-container").html(html);
}

// 调用函数生成日历HTML
buildCalendarHtml();

为什么这样可行?

  1. getDayTd是async函数,用await等待AJAX请求完成,拿到数据后直接生成td字符串并返回,这个函数本身会返回一个Promise。
  2. 我们把所有日期的请求Promise收集到数组里,用Promise.all并行等待所有请求完成,既能保证效率,又能一次性拿到所有结果。
  3. 所有异步操作完成后再拼接HTML,这时候你拿到的就是完整的、正确的表格单元格内容了。

兼容旧环境的替代方案:用jQuery Deferred

如果需要兼容不支持async/await的旧浏览器,可以用jQuery的Deferred对象处理:

function getDayTd(i) {
  const deferred = $.Deferred();
  $.ajax({
    url: "http://localhost:8888/vs-time-tracking-ajax-calendar/",
    data: { i: i },
    type: "POST",
    dataType: "json",
    success: function(data) {
      let tdClass = "ic__day";
      const targetDate = moment(timeNowLocal).date(data.i).format("D.M.YYYY");
      if (targetDate === timeNow.format("D.M.YYYY")) {
        tdClass = "ic__day ic__day_state_current";
      } else if (timeSelected && targetDate === timeSelected.format("D.M.YYYY")) {
        tdClass = "ic__day ic__day_state_selected";
      }
      deferred.resolve(`<td class="${tdClass}">${data.i}</td>`);
    },
    error: function(request) {
      alert(request.responseText);
      deferred.resolve(`<td class="ic__day ic__day_state_error">Error</td>`);
    }
  });
  return deferred.promise();
}

// 收集所有请求的Deferred对象
const promises = [];
for (let i = 1; i <= monthLastDay; i++) {
  promises.push(getDayTd(i));
}

// 等待所有请求完成后组装HTML
$.when.apply($, promises).done(function() {
  let html = "";
  // arguments中包含所有请求返回的td字符串
  for (const td of arguments) {
    html += td;
  }
  // 处理最终生成的HTML
  console.log(html);
});

关键注意点

  • 尽量不要在循环里串行等待每个AJAX请求(比如把await放在循环内),这样会让请求逐个执行,效率极低;用Promise.all并行发起请求是更优的选择。
  • 一定要处理错误情况,避免某个请求失败导致整个页面逻辑崩溃。
  • 循环里必须用let i而不是var i,否则闭包会导致所有请求拿到的都是最后一个循环值。

内容的提问来源于stack exchange,提问作者John M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:45:03