简体   繁体   English

异步jQuery请求计时问题

[英]Asynchronous jQuery request timing issue

As a learning exercise I've hacked together a script for an SO feature request (for the purposes of this question please ignore the merits or otherwise of that request). 作为学习练习,我为SO 功能请求编写了一个脚本(出于此问题的目的,请忽略该请求的优缺点)。 In the script I've encountered a technical issue that my limited javascript knowledge can't get past and I'd appreciate suggestions on how to resolve it. 在脚本中,我遇到了一个技术问题,即我有限的javascript知识无法摆脱,并且我很高兴提出解决问题的建议。

To avoid spamming the server I use some search hacks to determine the number of answers and accepted answers for a tag. 为了避免向服务器发送垃圾邮件,我使用一些搜索技巧来确定标签的答案数量和可接受的答案。 This involves using window.setTimeout() to callback to a function that sends a get request for each tag, increasing the timeout on each call to stagger the requests. 这涉及到使用window.setTimeout()回调到为每个标签发送获取请求的函数,从而增加了每次调用的超时以错开请求。

To get the results in a single request involves appending &pagesize=1 to the end of the url in the get request, so that the number of pages in the results gives you the total number of results without having to make any further requests. 要在单个请求中获得结果,需要将&pagesize = 1附加到get请求中的url末尾,这样结果中的页数就可以为您提供结果的总数,而无需发出任何其他请求。

A side affect of this approach is that subsequent page views use &pagesize=1 and I only see a single entry. 这种方法的副作用是后续的页面浏览量使用&pagesize = 1,而我只看到一个条目。 I attempt to resolve this by firing another query with &pagesize=30 to reset it afterwards, but as it is all asynchronous the timing of the last query can result in the pagesize either being 1 or 30, depending on which request completes first. 我尝试通过触发另一个带有&pagesize = 30的查询来解决此问题,然后将其重置,但是由于所有异步操作,最后一次查询的时间可能导致pagesize为1或30,具体取决于哪个请求首先完成。 I've tried adding a further timeout and callback for this "reset" query but it hasn't really helped. 我已经尝试为此“重置”查询添加更多的超时和回调,但并没有真正帮助。

Is there a means to monitor the queries, waiting until all have been completed, then once they have all completed send the reset request? 是否有一种监视查询的方法,等待所有查询完成,然后在所有查询完成后发送重置请求? Or is there another approach that I could take? 还是我可以采取另一种方法?

You could make a call chain 您可以拨打电话链

Based on my previous idea of a ParallelAjaxExecuter , here's a SerialAjaxExecuter 基于我之前对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 ) )
}

I didn't bake in a sleep period between requests, but that could certainly be added. 我没有在两次请求之间的睡眠时间里烘烤,但是可以肯定地添加它。 Added the timeout 添加了超时

Note: this example is littered with console.log() calls for which you need firebug, or just remove them. 注意:此示例到处都是console.log()调用,您需要对其进行调试或将其删除。

I'm not sure if I fully understand the problem but why not chain the requests rather than using a setTimeout ? 我不确定我是否完全理解问题,但是为什么不链接请求而不是使用setTimeout呢? So at the end of the response handler of one request fire off the next request. 因此,在一个请求的响应处理程序结束时,将触发下一个请求。

将&pagesize =附加到您当前正在使用的页面大小的页面上每个需要链接的地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM