【问题标题】:Repeat/loop ajax call on a timer - even if timed out在计时器上重复/循环 ajax 调用 - 即使超时
【发布时间】:2017-12-11 15:03:29
【问题描述】:

我们有一块显示板需要每秒更新一次。对服务器的 AJAX 调用触发了一个存储过程,它是一个非常简单的 SELECT 语句,执行只需几毫秒。

最初,由于网络延迟(或黑子,或谁知道),此 AJAX 进程有时会(偶尔,很少)超时。通过调整我们处理计时器的方式并将 timeout 设置为 0,我们得到了它,因此它现在运行稳定并且永远不会发生超时......但是。

话虽如此,我仍然担心超时可能仍然发生。如果发生了,目标是它会继续下去。基本上,忽略超时,然后再试一次......永远。没有像 MaxError、RetryLimit 或 TryCount 等。

这是我现在拥有的:

setTimeout(function run() {
    // When the timer elapses, get the data from the server
    GetData();
    setTimeout(run, _refreshRate);
}, 1000);


function GetData() {
    //console.log("Attempting to obtain the data...");
    jQuery.ajax({
        url: "something.ashx",
        type: "GET",
        contentType: 'application/json; charset=utf-8',
        success: function(resultData) {
            //console.log("Got the data.");
            ParseJson(resultData);
            // show the last refresh date and time
            $('#refreshTime').html(GetDateTime());
        },
        error : function(xhr, textStatus, errorThrown) {
            if (textStatus == 'timeout') {
                //console.log("Timeout occured while getting data from the server.  Trying again.");
                // If a timeout happens, DON'T STOP. Just keep going forever.
                $.ajax(this);
                return;
            }
         },
         timeout: 0,
    });
}

ParseJson(resultData); 里面的所有东西都很好用。那里没有问题。并且计时器已设置(我相信),因此它将等到一个 GetData() 完成后再尝试启动另一个。

我相信将timeout 设置为0 意味着“永远不要超时”。

我的问题是这样的:

我是否正确处理了error 超时?我使用此线程中的选定答案作为我的指南:

What's the best way to retry an AJAX request on failure using jQuery?

但我不需要 retryLimit 限制。

我也看过这些主题:

How to make the Ajax call again in case Time out error occurs

ajax timeout callback function

认为我已将所有信息归结为一个简单的解决方案,但我想要一些同行评审。有没有更好的方法来做到这一点?

【问题讨论】:

  • 从外观上看,它应该已经在发生了。您的 run 函数设置为每 1 秒执行一次。而且它设置在您的 ajax 调用范围之外,因此您的 ajax 调用是否超时无关紧要。你试过调试这个吗?
  • 每一秒都会给服务器带来沉重的负担。你真的应该使用 websockets 来做到这一点
  • @MattSpinks - 是的,很多。经过多次试验和错误,我们到了这一点,现在它似乎很稳定。我的意思是,它不再超时。至少,我们让它运行了几个小时并对其进行了大量测试,并且它从未超时,在它每隔几分钟就会运行一次。所以我认为我们很好。大多数情况下,我只是在寻找有关如何改进的任何同行建议,或者此代码中是否存在潜在的问题。
  • @charlietfl,谢谢!我真的很感激这个主意。我承认我没有想到 websockets,但这可能是一个更好的解决方案。好消息是运行的 SP 非常小。我们在 SQL Query Analyzer 和 Profiler 中对其进行了各种测试,而 database 服务器上的负载几乎不存在。那么,问题:websockets 将如何帮助降低 web 服务器上的负载?
  • 好的,很好。我可能会将您的机制更改为从您的 successerror 函数内部进行轮询,而不是在您的 run 函数中进行轮询。这样做的原因是,如果出现任何类型的网络错误,那么即使最后一个请求尚未返回,您的代码也不会盲目地发送更多请求。

标签: javascript jquery ajax settimeout


【解决方案1】:

我更喜欢仅在当前呼叫完成时才将新呼叫排队的解决方案。类似的东西..

function poll() {
  setTimeout(function () {
     GetData();
  }, 1000);
}

function GetData() {
    jQuery.ajax({
        url: "something.ashx",
        type: "GET",
        contentType: 'application/json; charset=utf-8',
        success: function(resultData) {
            //...
        },
        error : function(xhr, textStatus, errorThrown) {
            //...
        },
        complete: function() {
           poll();
        },
        timeout: 0,
    });
}

poll();

这样你的通话就不会有重叠的风险。

【讨论】:

  • 好的,这是有道理的。那么poll() 是否会在 $( document ).ready() 内部第一次被调用?
  • @CaseyCrookston 是的,这是可取的
  • 好的,complete 函数调用 poll() 即使有错误。对吗?
  • @CaseyCrookston 没错。不过有一件事:您在错误处理程序中调用$.ajax(this);(我假设进行新调用)。这不是必需的,因为完整处理程序将在一秒钟后启动一个新调用(无论是否出错)。
  • 是的,明白了。这要优雅得多。我现在正在测试这个。非常感谢!!!
【解决方案2】:
function GetData() {
    //console.log("Attempting to obtain the data...");
    jQuery.ajax({
        url: "something.ashx",
        type: "GET",
        contentType: 'application/json; charset=utf-8',
        success: function(resultData) {
            //console.log("Got the data.");
            ParseJson(resultData);
            // show the last refresh date and time
            $('#refreshTime').html(GetDateTime());
        },
        error : function(xhr, textStatus, errorThrown) {
            if (textStatus == 'timeout') {
                //console.log("Timeout occured while getting data from the server.  Trying again.");
                // If a timeout happens, DON'T STOP. Just keep going forever.
                $.ajax(this);
                return;
            }
         },
         timeout: 0,
    });
}

var myInterval = setInterval(getData, 1000)
// if you want to stop it elsewhere:
// clearInterval(myInterval)

你可以使用 setInterval 代替超时

【讨论】:

  • 可以,但这并不能解决当前设计中的任何问题。呼叫仍然有排队的风险,现在您有一个时间间隔来处理,而不是一劳永逸的超时。有什么好处? :)
  • 与您的解决方案相比,我可以保证每秒都会发出请求。您的解决方案没有考虑请求时间。但最后你是对的。对于他的需要,您的解决方案更适合。因此,我将我的答案留给其他用例,并将您的答案标记为有帮助。 ;)
  • 只是为了指出明显所说的内容,如果请求返回数据的时间超过超时时间,这可能会堆积请求 - 这可能在某处有一些用例
猜你喜欢
  • 2019-10-21
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
相关资源
最近更新 更多