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

主线程同步XMLHttpRequest已弃用,求async:false替代方案

同步AJAX报错的替代解决方案

问题背景

调用多个嵌套AJAX接口时,控制台抛出警告:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects for the end user’s experience

确认问题源于代码中设置的async:false,但移除该参数后页面渲染顺序混乱,显示异常。

核心原因

async:false会强制AJAX同步执行,阻塞浏览器主线程,导致页面卡顿、无响应,这也是浏览器将其标记为废弃的原因。原代码依赖同步的执行顺序:先获取所有分类,再逐个分类获取商品,最后按顺序渲染DOM。移除async:false后,异步请求会并行执行,导致DOM渲染顺序错乱,所以页面异常。

替代方案

方案1:使用Promise + async/await(推荐,代码更清晰)

利用ES6的async/await让异步代码以同步逻辑编写,同时保持异步执行,不阻塞主线程。结合jQuery 3.0+版本AJAX返回Promise对象的特性,可轻松改造代码:

修改后的代码:

<script>
// 封装获取分类的AJAX为Promise函数
async function getAllCategories() {
  return $.ajax({
    method: "POST",
    url: "API/actions/getAllCategories"
  });
}

// 封装获取分类商品的AJAX为Promise函数
async function getProductsByCatId(categoryId, countryId) {
  return $.ajax({
    method: "POST",
    url: "API/actions/getProductsbycatId",
    data: {
      "categoryId": categoryId,
      "countryId": `<?php echo $_SESSION['evoucher']['countryId'] ?> `
    }
  });
}

// 主逻辑用async/await控制顺序
async function renderCategoryTabs() {
  try {
    const categories = await getAllCategories();
    let newdiv = "";
    let count = 1;

    for (const row of categories) {
      // 构建导航项
      if (count === 1) {
        newdiv += `  <li class="active">
                      <a data-toggle="tab" href="#tab${count}" aria-expanded="true">
                        <span>${row.name}</span>
                      </a>
                    </li>`;
      } else {
        newdiv += `  <li>
                      <a data-toggle="tab" href="#tab${count}" aria-expanded="true">
                        <span>${row.name}</span>
                      </a>
                    </li>`;
      }

      // 等待当前分类的商品请求完成
      const products = await getProductsByCatId(row.id, `<?php echo $_SESSION['evoucher']['countryId'] ?> `);
      let active = count === 1 ? "active in" : "";
      let newdiv1 = ` <div id="tab${count}" class="tab-pane fade ${active}">
                        <div class="bbb_viewed">
                          <div class="row">
                            <div class="col">
                              <div class="bbb_main_container">
                                <div class="bbb_viewed_title_container">
                                  <div class="bbb_viewed_nav_container">
                                    <div class="bbb_viewed_nav bbb_viewed_prev"><i class="fas fa-chevron-left"></i></div>
                                    <div class="bbb_viewed_nav bbb_viewed_next"><i class="fas fa-chevron-right"></i></div>
                                  </div>
                                </div>
                                <div class="bbb_viewed_slider_container">
                                  <div class="owl-carousel owl-theme bbb_viewed_slider">`;

      products.forEach(row1 => {
        newdiv1 += `                            <div class="owl-item">
                                                  <div class="bbb_viewed_item1 discount d-flex flex-column align-items-center justify-content-center text-center">
                                                    <div class="bbb_viewed_image"><img src="${row1.pathimage2}" alt=""></div>
                                                    <div class="bbb_viewed_content text-center">
                                                      <div class="bbb_viewed_name"><a href="#">${row1.name}</a></div>
                                                    </div>
                                                  </div>
                                                </div>`;
      });

      newdiv1 += `                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>`;

      $("#tabs").append(newdiv1);
      count++;
    }

    $("#bestsellernav").html(newdiv);
    // 渲染完成后初始化轮播
    $('.bbb_viewed_slider').owlCarousel();
  } catch (error) {
    alert("加载数据失败");
    console.error(error);
  }
}

// 执行主函数
renderCategoryTabs();
</script>

方案2:使用jQuery的Deferred对象(兼容旧版jQuery)

如果项目使用jQuery 3.0以下版本,可通过$.Deferred管理异步流程:

<script>
function getAllCategories() {
  return $.ajax({
    method: "POST",
    url: "API/actions/getAllCategories"
  });
}

function getProductsByCatId(categoryId, countryId) {
  return $.ajax({
    method: "POST",
    url: "API/actions/getProductsbycatId",
    data: {
      "categoryId": categoryId,
      "countryId": `<?php echo $_SESSION['evoucher']['countryId'] ?> `
    }
  });
}

getAllCategories().done(function(categories) {
  let newdiv = "";
  let count = 1;
  // 用链式调用保证顺序
  let sequence = $.Deferred().resolve();

  categories.forEach(row => {
    sequence = sequence.then(function() {
      // 构建导航项
      if (count === 1) {
        newdiv += `  <li class="active">
                      <a data-toggle="tab" href="#tab${count}" aria-expanded="true">
                        <span>${row.name}</span>
                      </a>
                    </li>`;
      } else {
        newdiv += `  <li>
                      <a data-toggle="tab" href="#tab${count}" aria-expanded="true">
                        <span>${row.name}</span>
                      </a>
                    </li>`;
      }

      // 请求当前分类商品
      return getProductsByCatId(row.id, `<?php echo $_SESSION['evoucher']['countryId'] ?> `).done(function(products) {
        let active = count === 1 ? "active in" : "";
        let newdiv1 = ` <div id="tab${count}" class="tab-pane fade ${active}">
                          <div class="bbb_viewed">
                            <div class="row">
                              <div class="col">
                                <div class="bbb_main_container">
                                  <div class="bbb_viewed_title_container">
                                    <div class="bbb_viewed_nav_container">
                                      <div class="bbb_viewed_nav bbb_viewed_prev"><i class="fas fa-chevron-left"></i></div>
                                      <div class="bbb_viewed_nav bbb_viewed_next"><i class="fas fa-chevron-right"></i></div>
                                    </div>
                                  </div>
                                  <div class="bbb_viewed_slider_container">
                                    <div class="owl-carousel owl-theme bbb_viewed_slider">`;

        products.forEach(row1 => {
          newdiv1 += `                            <div class="owl-item">
                                                        <div class="bbb_viewed_item1 discount d-flex flex-column align-items-center justify-content-center text-center">
                                                          <div class="bbb_viewed_image"><img src="${row1.pathimage2}" alt=""></div>
                                                          <div class="bbb_viewed_content text-center">
                                                            <div class="bbb_viewed_name"><a href="#">${row1.name}</a></div>
                                                          </div>
                                                        </div>
                                                      </div>`;
        });

        newdiv1 += `                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>`;

        $("#tabs").append(newdiv1);
        count++;
      });
    });
  });

  // 所有请求完成后更新导航
  sequence.done(function() {
    $("#bestsellernav").html(newdiv);
    $('.bbb_viewed_slider').owlCarousel();
  });
}).fail(function(error) {
  alert("加载数据失败");
  console.error(error);
});
</script>

额外优化建议

  • 批量请求优化:后端新增接口一次性返回所有分类及对应商品数据,减少前端AJAX请求次数,提升性能。
  • 加载状态提示:请求过程中添加加载动画,避免页面长时间空白,提升用户体验。

内容的提问来源于stack exchange,提问作者maria jansian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 05:10:33