2016-08-19 76 views
0

我使用jQuery与jQuery,因为我们知道$.ajax返回承诺ajaxPromise。我的要求是:只有当所有的Ajax调用重试失败时,ajaxPromise捕获失败(我想处理ajax承诺回调函数内的错误)。jQuery ajax - 仅在所有重试失败时触发失败回调函数

我尝试下面的代码:

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回调?还是有其他的选择可以做到这一点?

+0

你知道如何扭曲的范围界定在JavaScript的?我不确定,但我相信在嵌套的ajax调用中,您的'triedCount'变量会丢失。也许尝试传递回调中的变量,然后在ajax调用中作为选项? –

+0

您是否预先知道返回哪个标题?如果是的话,你可以使用statuCode回调。 –

+0

@MridulKashyap'triedCount'变量没有作用域问题:) – coderz

回答

1
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); 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

编辑:错误抛出从失败的Ajax调用将在ajaxPromise回调xhr参数可用。

+1

我仍然在寻找一种方式顺便说一句。将更新,如果我找到了什么。 –

+0

也许'不同','然后'有帮助吗? – coderz

+0

如何更新答案不同于http://stackoverflow.com/a/39031614/?在'.fail()'链接到'ajaxPromise'的'this'和'xhr'是什么? – guest271314

1

您可以使用$.Deferred(),.rejectWith();以$.Deferred()beforeStartajaxOptions作为参数传递调用递归函数;如果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>