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

如何使complete函数等待fetchingFunction执行完毕后再执行?

解决异步函数执行顺序问题:让后续操作等待异步任务完成

你现在遇到的情况是fetchingFunction里的setTimeout是异步操作,而你原来的代码没做任何等待处理,导致complete回调直接先跑了,控制台先输出2再输出1。我帮你捋捋问题根源,然后给你调整好代码:

问题出在哪?

  1. fetchingFunction是异步逻辑,但你直接把它的返回值传给了$.ajax的url参数——可这个函数根本没返回有效URL,里面的setTimeout是完全独立的异步任务,和AJAX请求半毛钱关系都没有。
  2. AJAX因为拿到的url是undefined,会立刻报错并进入complete回调,自然就先执行fakeFunction2打印2了,而setTimeout要等2秒才会打印1。

解决方案:用Promise控制异步顺序

我们需要把fetchingFunction改成返回Promise的形式,这样就能用async/await或者Promise.then()来强制后续操作等它完成后再执行。

修改后的完整代码

HTML部分(保持不变)
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.0/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" />
<ul class="nav nav-tabs">
<li><a class='aaa_tab' href="#aaa" data-toggle="tab">AAA</a></li>
<li><a class='bbb_tab' href="#bbb" data-toggle="tab">BBB</a></li>
<li><a class='ccc_tab' href="#ccc" data-toggle="tab">CCC</a></li>
</ul>
<div class="tab-content" id="tabs">
<div class="tab-pane" id="aaa">...Content1...</div>
<div class="tab-pane" id="bbb">...Content2...</div>
<div class="tab-pane" id="ccc">...Content3...</div>
</div>
JavaScript部分(核心逻辑修改)
var loopControl = 0;

// 把fetchingFunction改成返回Promise的异步函数
function fetchingFunction() {
  return new Promise((resolve) => {
    setTimeout(function() {
      console.log("1");
      resolve(); // 异步任务完成后,触发resolve通知外部可以继续执行后续逻辑
    }, 2000);
  });
}

function fakeFunction2() {
  console.log("2");
}

$('[data-toggle=tab]').on('show.bs.tab', async function(e) {
  if (loopControl == 0) {
    e.preventDefault();
    var ref = $(this).attr('href').replace('#', '');
    loopControl = 1;
    
    // 等待fetchingFunction的异步任务完成
    await fetchingFunction();
    
    // 异步任务完成后,再执行后续操作
    fakeFunction2();
    $('.' + ref + '_tab').click();
    loopControl = 0;
  } else {
    loopControl = 0;
  }
});

额外补充:如果AJAX有实际用途

如果你原来的AJAX是要请求真实接口的,那可以把AJAX放在fetchingFunction完成后执行,比如让fetchingFunction返回接口URL:

function fetchingFunction() {
  return new Promise((resolve) => {
    setTimeout(function() {
      console.log("1");
      resolve('你的真实接口URL'); // 返回接口地址
    }, 2000);
  });
}

// 事件处理里的逻辑调整
$('[data-toggle=tab]').on('show.bs.tab', function(e) {
  if (loopControl == 0) {
    e.preventDefault();
    var ref = $(this).attr('href').replace('#', '');
    loopControl = 1;
    
    fetchingFunction().then((url) => {
      $.ajax({
        url: url,
        success: function() {
          // 接口请求成功后的自定义逻辑
        },
        complete: function() {
          fakeFunction2();
          $('.' + ref + '_tab').click();
          loopControl = 0;
        }
      });
    });
  } else {
    loopControl = 0;
  }
});

这样修改后,控制台会先输出1,等待2秒异步任务完成后再输出2,完全符合你的预期。

内容的提问来源于stack exchange,提问作者FJ Shen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:08:40