【问题标题】:Delay between repeated AJAX call to a web method对 Web 方法的重复 AJAX 调用之间的延迟
【发布时间】:2012-03-12 01:50:37
【问题描述】:

我有一个在客户端实现了 jquery 的 ASP.Net Web 应用程序。在 while 循环中,客户端 jquery 脚本对服务器端代码中的 Web 方法进行异步调用。该调用返回 jquery 用来更新用户的长时间运行的服务器端任务的状态。目标是让 jquery 重复调用服务器,直到状态完成,一旦完成,它就会退出 while 循环并通知用户任务完成。

我的问题是下面的代码在 while 循环中运行,但我想让它在每次调用之间延迟或休眠,以防止状态请求使服务器不堪重负。我尝试在下面的代码中调用 setTimeout,但它只适用于初始 ajax 调用,每个后续调用都背靠背发生。有没有办法有效地延迟对服务器的每次后续调用?这是实现我所描述的那种行为的最有效方法吗?理想情况下,我希望每次通话之间有 2-5 秒的延迟。

我有以下代码

客户端 Jquery:

var alertTimerId;
$('input[name=btnStatus]').click(function () {

    var result  = false;
    //Loop while server reports task complete is true
    while (!result) {
      alertTimerId = setTimeout(function () {
        $.ajax({
          type: "POST",
          url: "Default.aspx/GetStatus",
          data: "{}",
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          async: true,
          success: function (msg) {
            if(msg.d != false)
              result = msg.d;
          },
          error: function (xhr, ajaxOptions, thrownError) {
            alert('AJAX failure');
          }
        });
      }, 2000);


      if (count > 0) {
        count--;
      }
    }


  });

服务器端 ASP

[System.Web.Services.WebMethod]
        public static bool GetStatus()
        {
            return result;
        }

【问题讨论】:

    标签: javascript jquery asp.net ajax


    【解决方案1】:

    像下面这样的东西怎么样?这个想法是将 Ajax 调用封装在一个函数 doAjax() 中,然后从 Ajax 成功处理程序中,如果结果为 false,则使用 setTimeout() 排队另一个对 doAjax 的调用,否则你采取任何行动你想要一个真实的结果。 (您也可以选择从 Ajax 错误处理程序中调用 doAjax()。)

    $('input[name=btnStatus]').click(function () {
    
        function doAjax() {
           $.ajax({
              type: "POST",
              url: "Default.aspx/GetStatus",
              data: "{}",
              contentType: "application/json; charset=utf-8",
              dataType: "json",
              async: true,
              success: function (msg) {
                 if (!msg.d)
                     setTimeout(doAjax, 2000);
                 else {
                     // Success! Notify user here
                 }
              },
              error: function (xhr, ajaxOptions, thrownError) {
                alert('AJAX failure');
              }
           });
        }
    
        doAjax();
    
    });
    

    (注意:我已经删除了带有count 的 if 语句,因为它似乎与问题无关。如果您的实际代码使用它,只需在 Ajax 成功处理程序中更新它。)

    【讨论】:

    • 我也会将setTimeout(doAjax,2000); 添加到错误处理函数中,因此如果其中一个ajax 请求超时,请求链不会中断。
    • @shaun5 - 我想这是否合适取决于 OP,但我确实在我的解释中提到了它。 (虽然我可能不会在错误情况下为超时而烦恼,因为已经有一个警报,所以在用户处理它时会有一点延迟。将警报更改为关于是否重试的确认消息可能会更好或中止。)
    • @nnnnnn - 这很好用,没想到要使用递归调用。我唯一担心的是,客户端缓冲区或 jQuery 用来存储其函数队列的任何其他缓存介质(我很抱歉没有完全理解 jQuery 如何存储队列引用),是否会被填充甚至溢出,尤其是在处理非常长的任务时在服务器端?只是好奇这是否会成为一个问题。再次感谢。
    • 这不是真正的递归调用。 setTimeout() 语句将调用doAjax() 排队,这将在指定的延迟之后发生,但同时在setTimeout() 之后的任何语句都会立即继续执行,因此在这种情况下,当前的成功回调将结束。一次只会有一个 Ajax 调用在进行中,并且一次只有一个超时排队。绝对不同于直接从doAjax() 内部说doAjax()。注意:setTimeout 不是 jQuery 的东西,它是纯 JavaScript 的东西。见developer.mozilla.org/en/DOM/window.setTimeout
    【解决方案2】:

    Underscore.Js 有一个 .throttle() 辅助函数:

    throttle_.throttle(函数,等待)

    创建并返回一个新的、受限制的传递函数的版本,当被调用时 重复,实际上最多只会调用一次原始函数 每等待毫秒。对于限速事件很有用 发生的速度比你跟得上的快。

    var throttled = _.throttle(updatePosition, 100);
    $(window).scroll(throttled);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-10
      • 2019-03-15
      • 2016-04-10
      • 1970-01-01
      • 1970-01-01
      • 2019-05-31
      • 2015-08-21
      • 2017-03-30
      相关资源
      最近更新 更多