Асинхронная проблема синхронизации запросов jQuery - PullRequest
2 голосов
/ 11 сентября 2009

В качестве учебного упражнения я собрал скрипт для запроса функции SO (для целей этого вопроса, пожалуйста, не обращайте внимания на достоинства или нет этого запроса). В сценарии я столкнулся с технической проблемой, которую мои ограниченные знания JavaScript не могут обойти, и я был бы признателен за предложения по ее решению.

Чтобы избежать спама на сервере, я использую некоторые хаки поиска, чтобы определить количество ответов и принятых ответов для тега. Это включает использование window.setTimeout () для обратного вызова функции, которая отправляет запрос get для каждого тега, увеличивая время ожидания для каждого вызова, чтобы разбить запросы.

Чтобы получить результаты в одном запросе, необходимо добавить & pagesize = 1 в конец URL-адреса в запросе get, чтобы количество страниц в результатах давало вам общее количество результатов без необходимости выполнения каких-либо дополнительных запросов. ,

Побочным эффектом этого подхода является то, что последующие просмотры страниц используют & pagesize = 1, и я вижу только одну запись. Я пытаюсь решить эту проблему, запустив другой запрос с & pagesize = 30, чтобы впоследствии сбросить его, но, поскольку он все асинхронный, синхронизация последнего запроса может привести к размеру страницы, равному 1 или 30, в зависимости от того, какой запрос завершается первым. Я попытался добавить дополнительное время ожидания и обратный вызов для этого запроса на «сброс», но это не помогло.

Существуют ли средства для отслеживания запросов, ожидая, пока все не будут завершены, и затем, после того как все они будут завершены, отправить запрос на сброс? Или есть другой подход, который я мог бы выбрать?

Ответы [ 3 ]

5 голосов
/ 11 сентября 2009

Вы можете сделать цепочку вызовов

Основываясь на моей предыдущей идее 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, или просто удалите их.

0 голосов
/ 11 сентября 2009

Добавить & pagesize = к каждой ссылке на странице, которая будет нужна с тем размером страницы, который вы используете в данный момент.

0 голосов
/ 11 сентября 2009

Я не уверен, что полностью понимаю проблему, но почему бы не объединить запросы вместо использования setTimeout? Таким образом, в конце обработчик ответа одного запроса запускает следующий запрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...