为什么这个ajax调用中的错误回调是交替执行的

时间:2014-11-02 07:26:48

标签: javascript jquery ajax

我有以下JQuery代码,每20秒进行一次ajax调用。

var uiBlocked = false;
var timerCount = 20;
window.setInterval(function() {
 $.ajax({
   cache: false,
   type: 'HEAD',
   url: '/heartbeat/',
   timeout: 1000,
   async: true,
   success: function(data, textStatus, XMLHttpRequest) {
    if (uiBlocked == true && navigator.onLine) {
       uiBlocked = false;
       $.unblockUI();
      }
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
    if(textStatus != 'timeout'){
      if (uiBlocked == false){
          uiBlocked = true;
          alert(textStatus);
          $.blockUI({
            message: 'Lost connectivity, please reconnect your VPN.<br/>Retrying in <span  id="timer">20</span> .... secs.',
            css: {
             border: 'none',
             padding: '15px',
             backgroundColor: '#000',
             '-webkit-border-radius': '10px',
             '- moz-border-radius': '10px',
             opacity: .5,
             color: '#fff'
           },
           onBlock: function counterFunction() {
               document.getElementById("timer").innerHTML= timerCount;
               timerCount--;
               if(timerCount >= 0){
                  setTimeout(counterFunction, 1000);
               }
               else{
                  timerCount = 20;
                  uiBlocked = false;
               }
           }
        });
      }
    }
  }
 })
}, 20000);

在我的错误部分中,我调用setTimeout函数来递减计数器。计数器递减并发出警报,计数器重置为20秒。但是在第二次调用时,错误回调不会被执行。这再次在第三次调用时执行。

我的计时器出错了吗?任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:0)

这听起来像定时器和间隔的古怪行为以及JS是单线程的事实。

它绝不是一个解决方案,但我建议查看John Resig的这篇伟大帖子 - 也就是jQuery先生。

How JavaScript Timers Work

我有他创作的JS Ninja Book,它有一个类似的章节,对我来说真是令人大开眼界这些操作符的行为。

答案 1 :(得分:0)

我认为您的问题可能需要setInterval而不是递归setTimeout

在这里,我制作了一个jsFiddle来简化您的问题,以便更容易理解:

$(function(){
   var i = 20,
       interval;

    $('#button').click(function(){
        i = 20;

        if (interval){
            clearInterval(interval)
        }

        interval = setInterval(function(){
            if (i >= 0){
                $('#counter').text(i--);
            } else {
                clearInterval(interval) 
            }
        }, 1000);
    });
});

正如您所看到的,重置i变量(示例中为timerCount)以及对先前声明的clearInterval() <setInterval()进行操作非常重要/ p>

更新

在你的情况下

var timer;
// ....

onBlock: function counterFunction() {
    timerCount = 20;
    if (iterval) {
        clearInterval(interval);
    }
    interval = setInterval(function() {
        if (timerCount >= 0) {
            $('#timer').text(--timerCount);
        } else {
            clearInterval(interval);
            uiBlocked = false;
        }
    }, 1000);
}