【问题标题】:jQuery ajax - trigger fail callback function only when all retry failedjQuery ajax - 仅在所有重试失败时触发失败回调函数
【发布时间】:2016-08-19 04:31:02
【问题描述】:

我使用 ajax 和 jQuery,我们知道 $.ajax 返回一个承诺 ajaxPromise。我的要求是:只有当所有ajax调用重试都失败时,ajaxPromise才捕获失败(我想在ajax promise回调函数中处理错误)。

我尝试了以下代码:

function ajax(data) {
  return $.ajax({
    url: "...",
    data: data,
    triedCount: 0,
    retryLimit: 3,
    error: function(xhr, textStatus, errorThrown ) {
      console.log("error: " + this.triedCount);
      this.triedCount++;
      if (this.triedCount < this.retryLimit) {
        $.ajax(this);
      }
    }
  });
}

var ajaxPromise = ajax({"id": "123"});
ajaxPromise.fail(function(xhr) {
  console.log("All retries failed...");
  // all retries failed, handle error
});

输出我想要的是:

error: 0
error: 1
error: 2
All retries failed...

虽然实际上输出是:

error: 0
All retries failed...
error: 1
error: 2

看起来fail回调在第一次调用失败后立即触发,而我希望在所有重试失败后触发fail回调。

有没有什么办法只有在所有重试失败时才触发ajaxPromise.fail回调?还是有其他选择可以做到这一点?

【问题讨论】:

  • 你知道 javascript 的作用域有多扭曲吗?我不确定,但我相信嵌套的 ajax 调用,你的 triedCount 变量丢失了。也许尝试在回调中传递变量,然后作为选项在 ajax 调用中传递?
  • 你提前知道返回的是哪个标头吗?如果是,您可以使用 statuCode 回调。
  • @MridulKashyap triedCount 变量没有范围问题:)
  • @coderz:我建议你将所有的promises(包括重试承诺)的ajax调用推到一个数组中
  • 为什么不尝试使用 async : false

标签: javascript jquery ajax


【解决方案1】:

您可以使用$.Deferred().rejectWith();使用$.Deferred()beforeStart 调用递归函数,并将ajaxOptions 作为参数传递;如果this.triedCount 不小于this.retryLimit,则返回被拒绝的延迟对象,其中this 设置为当前的ajax 选项,xhr 作为参数传递给.fail(),链接到ajaxPromise

function ajax(data) {
  var ajaxOptions = {
    url: "...",
    data: data,
    triedCount: 0,
    retryLimit: 3
  };
  return new $.Deferred(function(dfd) {
    function request(opts) {
      $.ajax(opts)
        .fail(function(xhr, textStatus, errorThrown) {
          console.log("error: " + this.triedCount);
          this.triedCount++;
          if (this.triedCount < this.retryLimit) {
            return request(this)
          } else {
            dfd.rejectWith(this, [xhr])
          }
        })
    }
    request(ajaxOptions)
  })
}

var ajaxPromise = ajax({
  "id": "123"
});
ajaxPromise.fail(function(xhr) {
  console.log("All retries failed...", xhr);
  // all retries failed, handle error
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

【讨论】:

    【解决方案2】:
    function ajax(data) {
      return $.ajax({
        url: "...",
        data: data,
        triedCount: 0,
        retryLimit: 3,
        error: function(xhr, textStatus, errorThrown ) {
          console.log("error: " + this.triedCount);
          this.triedCount++;
          if (this.triedCount < this.retryLimit) {
            console.log(this);
            $.ajax(this);
          }
        }
      });
    }
    

    在您的代码中,如果发生错误,您将调用 ajax 函数。但这并不意味着之前的 ajax 调用没有完成。第一个 ajax 调用完成并发送返回值(失败)。你的

    ajaxPromise.fail(function(xhr) {
     console.log("All retries failed...");
      // all retries failed, handle error
    });
    

    运行,你得到“所有重试失败...”登录到控制台。 如果你想达到你想要达到的效果,你必须拦截以前的结果并防止它被返回。相反,检查 3 次尝试是否已完成,然后返回值。但我不知道该怎么做。

    编辑:经过长时间的研究,我发现这是不可能的。你应该放弃尝试做这样的事情..开个玩笑!检查这段代码,我相信这正是你想要的:

    // Code goes here
    
    function ajax(data) {
      var dfd = $.Deferred();
      $.ajax({
        url: "...",
        data: data,
        triedCount: 0,
        retryLimit: 3,
        success: function(){
          dfd.resolve("success");
        },
        error: function(xhr, textStatus, errorThrown ) {
          console.log("error: " + this.triedCount);
          this.triedCount++;
          if (this.triedCount < this.retryLimit) {
            $.ajax(this);
          }
          else{
            dfd.reject(xhr);
          }
        }
      });
      return dfd.promise();
    }
    var ajaxPromise = ajax({"id": "123"});
    ajaxPromise.fail(function(xhr) {
      console.log("All retries failed...");
      // all retries failed, handle error
      console.log(xhr.responseText);
    });
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    编辑:失败的 ajax 调用引发的错误将在 ajaxPromise 回调的 xhr 参数中可用。

    【讨论】:

    • 顺便说一句,我仍在寻找方法。如果我找到东西会更新。
    • 也许differed, then 有帮助?
    • 更新的答案与stackoverflow.com/a/39031614有何不同?链接到ajaxPromise.fail() 上的thisxhr 是什么?
    • 它使用相同的方法来实现目标。但如您所见,此代码非常接近 OP 发布的原始代码。另外,我想它对初学者(比如我自己)来说更干净,更容易理解。关于xhr 是的,我忘了在.reject() 中添加返回值。谢谢你指出。我会更新的。
    • 检查这个plunk idk 为什么responseText 没有显示在这里。
    猜你喜欢
    • 2013-11-14
    • 2014-05-14
    • 2011-04-06
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 2023-01-02
    • 1970-01-01
    相关资源
    最近更新 更多