Найдите что-либо подобное асинхронным запросам Ajax с помощью jQuery

Некоторые посты показали, как отображать прогресс команды. Чтобы рассчитать это, вам нужно увидеть, насколько вы продвинулись. В системах BSD некоторые команды, такие как dd (1), принимают сигнал SIGINFO и сообщают о своем прогрессе. В системах Linux некоторые команды будут реагировать аналогично SIGUSR1. Если эта возможность доступна, вы можете направить свой ввод через dd, чтобы отслеживать количество обработанных байтов.

В качестве альтернативы, вы можете использовать lsof , чтобы получить смещение указателя чтения файла и, таким образом, рассчитать прогресс. Я написал команду с именем pmonitor , которая отображает ход обработки указанного процесса или файла. С его помощью вы можете делать такие вещи, как следующие.

$ pmonitor -c gzip
/home/dds/data/mysql-2015-04-01.sql.gz 58.06%

Более ранняя версия сценариев оболочки Linux и FreeBSD появилась в моем блоге .

73
задан Chris Pietschmann 29 June 2009 в 21:12
поделиться

6 ответов

Попробуйте это решение, которое может поддерживать любое количество параллельных запросов:

var done = 4; // number of total requests
var sum = 0;

/* Normal loops don't create a new scope */
$([1,2,3,4,5]).each(function() {
  var number = this;
  $.getJSON("/values/" + number, function(data) {
    sum += data.value;
    done -= 1;
    if(done == 0) $("#mynode").html(sum);
  });
});
102
ответ дан 24 November 2019 в 12:06
поделиться

Вот моя попытка напрямую ответить на ваш вопрос

По сути, вы просто создаете стек вызовов AJAX, выполняете их все, и по завершении всех событий вызывается предоставленная функция - предоставленный аргумент является массивом результатов всех предоставленных запросов ajax.

Очевидно, что это ранний код - вы могли бы уточнить его с точки зрения гибкости.

<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">

var ParallelAjaxExecuter = function( onComplete )
{
  this.requests = [];
  this.results = [];
  this.onComplete = onComplete; 
}

ParallelAjaxExecuter.prototype.addRequest = function( method, url, data, format )
{
  this.requests.push( {
      "method"    : method
    , "url"       : url
    , "data"      : data
    , "format"    : format
    , "completed" : false
  } )
}

ParallelAjaxExecuter.prototype.dispatchAll = function()
{
  var self = this;
  $.each( self.requests, function( i, request )
    {
    request.method( request.url, request.data, function( r )
    {
      return function( data )
      {
        console.log
        r.completed = true;
        self.results.push( data );
        self.checkAndComplete();
      }
    }( request ) )
  } )
}

ParallelAjaxExecuter.prototype.allRequestsCompleted = function()
{
  var i = 0;
  while ( request = this.requests[i++] )
  {
    if ( request.completed === false )
    {
      return false;
    }
  }
  return true;
},

ParallelAjaxExecuter.prototype.checkAndComplete = function()
{
  if ( this.allRequestsCompleted() )
  {
    this.onComplete( this.results );
  }
}

var pe = new ParallelAjaxExecuter( function( results )
{
  alert( eval( results.join( '+' ) ) );
} );

pe.addRequest( $.get, 'test.php', {n:1}, 'text' );
pe.addRequest( $.get, 'test.php', {n:2}, 'text' );
pe.addRequest( $.get, 'test.php', {n:3}, 'text' );
pe.addRequest( $.get, 'test.php', {n:4}, 'text' );

pe.dispatchAll();

</script>

здесь test.php

<?php

echo pow( $_GET['n'], 2 );

?>
9
ответ дан 24 November 2019 в 12:06
поделиться

вы можете сделать что-то вроде этого

var allData = []
$.getJSON("/values/1", function(data) {
    allData.push(data);
    if(data.length == 2){
      processData(allData) // where process data processes all the data
    }
});

$.getJSON("/values/2", function(data) {
    allData.push(data);
    if(data.length == 2){
        processData(allData) // where process data processes all the data
    }
});

var processData = function(data){
     var sum = data[0] + data[1]
     $('#mynode').html(sum);
}
5
ответ дан 24 November 2019 в 12:06
поделиться

Если результат одного запроса зависит от другого, вы не можете сделать их параллельными.

1
ответ дан 24 November 2019 в 12:06
поделиться

Обновление: Согласно ответу Яира Левиэля, этот ответ устарел. Используйте библиотеку обещаний, например jQuery.when () или Q.js.


Я создал решение общего назначения как расширение jQuery. Можно было бы использовать некоторую тонкую настройку, чтобы сделать его более общим, но это соответствовало моим потребностям. Преимущество этого метода перед другими в этой публикации на момент написания этой статьи состояло в том, что можно было использовать любой тип асинхронной обработки с обратным вызовом.

Примечание: я бы использовал расширения Rx для JavaScript вместо этого, если бы думал, что мой клиент не возражает против использования еще одной сторонней библиотеки :)

// jQuery extension for running multiple async methods in parallel
// and getting a callback with all results when all of them have completed.
//
// Each worker is a function that takes a callback as its only argument, and
// fires up an async process that calls this callback with its result.
//
// Example:
//      $.parallel(
//          function (callback) { $.get("form.htm", {}, callback, "html"); },
//          function (callback) { $.post("data.aspx", {}, callback, "json"); },
//          function (formHtml, dataJson) { 
//              // Handle success; each argument to this function is 
//              // the result of correlating ajax call above.
//          }
//      );

(function ($) {

    $.parallel = function (anyNumberOfWorkers, allDoneCallback) {

    var workers = [];
    var workersCompleteCallback = null;

    // To support any number of workers, use "arguments" variable to
    // access function arguments rather than the names above.
    var lastArgIndex = arguments.length - 1;
    $.each(arguments, function (index) {
        if (index == lastArgIndex) {
            workersCompleteCallback = this;
        } else {
            workers.push({ fn: this, done: false, result: null });
        }
    });

    // Short circuit this edge case
    if (workers.length == 0) {
        workersCompleteCallback();
        return;
    }

    // Fire off each worker process, asking it to report back to onWorkerDone.
    $.each(workers, function (workerIndex) {
        var worker = this;
        var callback = function () { onWorkerDone(worker, arguments); };
        worker.fn(callback);
    });

    // Store results and update status as each item completes.
    // The [0] on workerResultS below assumes the client only needs the first parameter
    // passed into the return callback. This simplifies the handling in allDoneCallback,
    // but may need to be removed if you need access to all parameters of the result.
    // For example, $.post calls back with success(data, textStatus, XMLHttpRequest).  If
    // you need textStatus or XMLHttpRequest then pull off the [0] below.
    function onWorkerDone(worker, workerResult) {
        worker.done = true;
        worker.result = workerResult[0]; // this is the [0] ref'd above.
        var allResults = [];
        for (var i = 0; i < workers.length; i++) {
            if (!workers[i].done) return;
            else allResults.push(workers[i].result);
        }
        workersCompleteCallback.apply(this, allResults);
    }
};

})(jQuery);
9
ответ дан 24 November 2019 в 12:06
поделиться

ОБНОВЛЕНИЕ И еще два года спустя это выглядит безумным, потому что принятый ответ изменился на что-то намного лучшее! (Хотя все еще не так хорошо, как ответ Яира Левиэля с использованием jQuery , когда )

18 месяцев спустя я просто наткнулся на нечто подобное. У меня есть кнопка обновления, и я хочу, чтобы старый контент был fadeOut , а новый контент - fadeIn . Но мне также нужно получить новый контент. fadeOut и get являются асинхронными, но запускать их поочередно было бы пустой тратой времени.

То, что я делаю, действительно совпадает с принятым ответом, за исключением формы многоразовой функции. Его главное достоинство в том, что он намного короче, чем другие предлагаемые здесь.

var parallel = function(actions, finished) {

  finishedCount = 0;
  var results = [];

  $.each(actions, function(i, action) {

    action(function(result) {

      results[i] = result;
      finishedCount++;

      if (finishedCount == actions.length) {
        finished(results);
      }
    });
  });
};

Вы передаете ему массив функций для параллельного выполнения. Каждая функция должна принимать другую функцию, которой она передает свой результат (если есть). Эту функцию будет выполнять parallel .

Вы также передаете ему функцию, которая будет вызываться после завершения всех операций. Он получит массив со всеми результатами. Итак, мой пример:

refreshButton.click(function() {

  parallel([
       function(f) { 
         contentDiv.fadeOut(f); 
       },
       function(f) { 
         portlet.content(f); 
       },
     ], 
     function(results) {
      contentDiv.children().remove();
      contentDiv.append(results[1]);
      contentDiv.fadeIn();
  });
});

Итак, когда моя кнопка обновления нажата, я запускаю эффект jQuery fadeOut , а также свой собственный портлет .content (которая выполняет async get , создает новый бит контента и передает его), а затем, когда оба они завершены, я удаляю старый контент, добавляю результат второй функции ( который находится в результатах [1] ) и fadeIn новый контент.

Поскольку fadeOut ничего не передает своей функции завершения, results [0] предположительно содержит undefined , поэтому я игнорирую его. Но если бы у вас было три операции с полезными результатами, они бы поместили каждый слот в массив results в том же порядке, в котором вы передали функции.

7
ответ дан 24 November 2019 в 12:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: