【问题标题】:Asynchronous jQuery request timing issue异步 jQuery 请求计时问题
【发布时间】:2010-11-27 13:54:57
【问题描述】:

作为学习练习,我为 SO feature request 编写了一个脚本(出于此问题的目的,请忽略该请求的优点或其他方面)。在脚本中,我遇到了一个技术问题,我有限的 javascript 知识无法解决,我很感激有关如何解决它的建议。

为了避免向服务器发送垃圾邮件,我使用了一些搜索技巧来确定标签的答案数量和接受的答案。这涉及使用 window.setTimeout() 回调一个函数,该函数为每个标签发送一个 get 请求,增加每次调用的超时时间以错开请求。

要在单个请求中获取结果,需要将 &pagesize=1 附加到 get 请求中 url 的末尾,以便结果中的页数为您提供结果总数,而无需进行任何进一步的请求.

这种方法的一个副作用是后续页面查看使用 &pagesize=1,而我只看到一个条目。我尝试通过使用 &pagesize=30 触发另一个查询来解决此问题,然后将其重置,但由于它都是异步的,因此最后一个查询的时间可能导致页面大小为 1 或 30,具体取决于哪个请求首先完成。我已经尝试为这个“重置”查询添加进一步的超时和回调,但它并没有真正帮助。

有没有办法监控查询,等到全部完成,然后在全部完成后发送重置请求?或者我可以采取其他方法吗?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    你可以建立一个调用链

    基于my previous idea of a ParallelAjaxExecuter,这里有一个SerialAjaxExecuter

    $(function(){
    
      var se = new SerialAjaxExecuter( function( results )
      {
        console.log( results );
      }, 1000 );
    
      se.addRequest( $.get, 'test.php', {n:1}, function( d ){ console.log( '1 done', d ); }, 'text' );
      se.addRequest( $.get, 'test.php', {n:2}, function( d ){ console.log( '2 done', d ); }, 'text' );
      se.addRequest( $.get, 'test.php', {n:3}, function( d ){ console.log( '3 done', d ); }, 'text' );
      se.addRequest( $.get, 'test.php', {n:4}, function( d ){ console.log( '4 done', d ); }, 'text' );
    
      se.execute();
    
    });
    
    var SerialAjaxExecuter = function( onComplete, delay )
    {
      this.requests = [];
      this.results  = [];
      this.delay    = delay || 1;
      this.onComplete = onComplete; 
    }
    
    SerialAjaxExecuter.prototype.addRequest = function( method, url, data, callback, format )
    {
      var self = this;
      this.requests.push( {
          "method"    : method
        , "url"       : url
        , "data"      : data
        , "format"    : format
        , "callback"  : callback
      } );
      var numRequests = this.requests.length;
      if ( numRequests > 1 )
      {
        this.requests[numRequests-2].callback = function( nextRequest, completionCallback )
        {
          return function( data )
          {
            completionCallback( data );
            setTimeout( function(){ self.execute( nextRequest ); }, self.delay );
          }
        }( this.requests[numRequests-1], this.requests[numRequests-2].callback )
      }
    }
    
    SerialAjaxExecuter.prototype.execute = function( request )
    {
      var self = this;
      if ( 'undefined' == typeof request )
      {
        request = this.requests[0];
        var lastRequest = this.requests[this.requests.length-1];
        lastRequest.callback = function( completionCallback )
        {
          return function( data  )
          {
              completionCallback( data )
              self.onComplete( self.results );
          }
        }( lastRequest.callback )
      }
      request.method( request.url, request.data, function( r )
      {
        return function( data )
        {
          self.results.push( data );
          r.callback( data );
        }
      }( request ) )
    }
    

    我没有在请求之间进行睡眠时间,但这当然可以添加。添加了超时

    注意:此示例中充斥着 console.log() 调用,您需要使用 firebug,或者直接删除它们。

    【讨论】:

    • 工作得很好,只有一个问题,在您的回答中,您的第一个请求从 1 开始,在我的实现中,我从 0 开始并且效果很好。它应该有什么不同吗?
    • 没有区别 - 这些只是任意标签。在内部,它作为一种链表类型结构处理。很高兴它对你有用:D
    【解决方案2】:

    我不确定我是否完全理解问题,但为什么不链接请求而不是使用setTimeout?因此,在一个请求的响应处理程序结束时,会触发下一个请求。

    【讨论】:

    • 听起来很有道理,你能举个例子吗?
    【解决方案3】:

    将 &pagesize= 附加到页面上需要它的每个链接以及您当前使用的页面大小。

    【讨论】:

    • 我特意设置了pagesize=1来作为统计匹配数的设备,如果我使用pagesize=30,我需要把最后一页的数字算总向上匹配,这意味着对列表中的每个项目有两个额外的请求
    • 也许我不明白...您将 'pagesize=1' 添加到 ajax 查询中,它会“破坏”您的正常浏览?
    • 这不是一个 ajax 查询,只是一个油脂猴脚本中的 jquery get 请求。我已经在 meta 的链接中发布了源代码。
    • 对我来说这看起来像是一个 ajax 查询;)我的想法是,改为使用 pagesize=30 执行另一个 $.get 请求,将其附加到页面上的所有链接。因此,当您点击某个内容时,您不会看到有 1 个结果的页面。
    • 是的,正如您所说,将 pagesize 添加到页面链接只是部分答案,如果在同一站点上打开另一个选项卡,它将不起作用。
    猜你喜欢
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    • 2019-06-03
    • 2016-04-25
    • 1970-01-01
    • 2011-06-06
    相关资源
    最近更新 更多