Вопрос

Я использую jQuery.И мне не нужны параллельные вызовы AJAX в моем приложении, каждый вызов должен дождаться предыдущего перед запуском.Как это реализовать?Есть какой-нибудь помощник?

ОБНОВЛЯТЬ Я хотел бы знать, существует ли какая-либо синхронная версия XMLHttpRequest или jQuery.post.Но последовательное != синхронное, и мне хотелось бы асинхронное и последовательное решение.

Это было полезно?

Решение

Есть гораздо лучший способ сделать это, чем использовать синхронные вызовы ajax.Jquery ajax возвращает отложенный вызов, поэтому вы можете просто использовать цепочку каналов, чтобы убедиться, что каждый вызов ajax завершается до следующего запуска.Вот рабочий пример с более подробным примером, который вы можете поиграй на jsfiddle.

// How to force async functions to execute sequentially 
// by using deferred pipe chaining.

// The master deferred.
var dfd = $.Deferred(),  // Master deferred
    dfdNext = dfd; // Next deferred in the chain
    x = 0, // Loop index
    values = [], 

    // Simulates $.ajax, but with predictable behaviour.
    // You only need to understand that higher 'value' param 
    // will finish earlier.
    simulateAjax = function (value) {
        var dfdAjax = $.Deferred();

        setTimeout(
            function () {
                dfdAjax.resolve(value);
            },
            1000 - (value * 100)
        );

        return dfdAjax.promise();
    },

    // This would be a user function that makes an ajax request.
    // In normal code you'd be using $.ajax instead of simulateAjax.
    requestAjax = function (value) {
        return simulateAjax(value);
    };

// Start the pipe chain.  You should be able to do 
// this anywhere in the program, even
// at the end,and it should still give the same results.
dfd.resolve();

// Deferred pipe chaining.
// What you want to note here is that an new 
// ajax call will not start until the previous
// ajax call is completely finished.
for (x = 1; x <= 4; x++) {

    values.push(x);

    dfdNext = dfdNext.pipe(function () {
        var value = values.shift();
        return requestAjax(value).
            done(function(response) {
                // Process the response here.

            });

    });

}

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

Другие советы

У вас есть два варианта, о которых я могу думать.Один из них — объединить их посредством обратных вызовов.Другой — сделать вызовы синхронными, а не асинхронными.

Есть ли причина, по которой вы хотите, чтобы они были последовательными?Это замедлит дело.

Чтобы сделать вызов синхронным, вы установите для параметра async в вызове Ajax значение false.См. документацию на http://docs.jquery.com/Ajax/jQuery.ajax#options (нажмите вкладку параметров, чтобы увидеть их).

Вы можете попробовать повествовательный JavaScript. http://www.neilmix.com/narrativejs/doc/

Хотя сам я никогда им не пользовался.Если бы я хотел это сделать, я бы установил какую-то абстракцию для объединения асинхронных действий.Как уже говорили другие, синхронная версия объекта ajax блокирует обработку событий, пока она ожидает ответа.Из-за этого браузер выглядит так, как будто он завис, пока не получит ответ.

Лучший способ сделать это — объединить обратные вызовы в цепочку, как сказал Носредна.Я бы не рекомендовал использовать синхронный XMLHttpRequest, поскольку они блокируют все ваше приложение.

Насколько я знаю, для этого не так уж много помощников, но вы можете сделать что-то вроде FIFO обратного вызова.

Посмотри на это: http://docs.jquery.com/Ajax/jQuery.ajax (нажмите на вкладку «Параметры»).

Но помните, что синхронный вызов заморозит страницу до тех пор, пока не будет получен ответ, поэтому его нельзя использовать на рабочем сайте, поскольку пользователи разозлятся, если по какой-либо причине им придется ждать 30 секунд с зависшим браузером.

РЕДАКТИРОВАТЬ:ок, с вашим обновлением стало яснее, чего вы хотите достичь ;)

Итак, ваш код может выглядеть так:

    $.getJSON("http://example.com/jsoncall", function(data) {
        process(data);
        $.getJSON("http://example.com/jsoncall2", function (data) {
            processAgain(data);
            $.getJSON("http://example.com/anotherjsoncall", function(data) {
                processAgainAndAgain(data);
            });
        });
    });

Таким образом, второй вызов будет отправлен только тогда, когда ответ на первый вызов будет получен и обработан, а третий вызов будет отправлен только тогда, когда ответ на второй вызов будет получен и обработан.Этот код предназначен для getJSON, но его можно адаптировать к $.ajax.

Установить асинхронный вариант false, например,

$.ajax({ async: false /*, your_other_ajax_options_here */ });

Ссылка: Аякс/jQuery.ajax

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

(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. запрашивает 3 файла json с помощью вызовов jQuery ajax
  2. обрабатывать последовательно (не параллельно) с ожиданием
  3. работает в Chrome/Firefox/Edge (по состоянию на 30.01.2018)

больше на МДН

Вы можете использовать обещание, чтобы сделать вызовы ajax последовательными.Используя метод Array push и pop Promise, последовательные вызовы ajax станут намного проще.

var promises = [Promise.resolve()];

function methodThatReturnsAPromise(id) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: 'https://jsonplaceholder.typicode.com/todos/'+id,
      dataType:'json',
      success: function(data)
      {
        console.log("Ajax Request Id"+id);
        console.log(data);
        resolve();
      }
    });
  });
} 

function pushPromise(id)
{
  promises.push(promises.pop().then(function(){
    return methodThatReturnsAPromise(id)}));
}


pushPromise(1);
pushPromise(3);
pushPromise(2);

Как насчет использования событий Node.js?

var EventEmitter = require('events').EventEmitter;
var eventEmitter = new EventEmitter();
var $ = require('jquery');

var doSomething = function (responseData) {
  var nextRequestData = {};
  // do something with responseData
  return nextRequestData;
};

// ajax requests
var request1 = $.ajax;
var request2 = $.ajax;
var requests = [request1, request2];

eventEmitter.on('next', function (i, requestData) {
  requests[i](requestData).then(
    function (responseData) {
      console.log(i, 'request completed');
      if (i+1 < requests.length) {
        var nextRequestData = doSomething(responseData);
        eventEmitter.emit('next', i+1, nextRequestData);
      }
      else {
        console.log('completed all requests');
      }
    },
    function () {
      console.log(i, 'request failed');
    }
  );
});

var data = {
  //data to send with request 1
};
eventEmitter.emit('next', 0, data);

sequential != синхронно, и мне хотелось бы асинхронное и последовательное решение

Синхронное выполнение обычно означает «использование одних и тех же часов», тогда как последовательное выполнение означает «следование по порядку или последовательности».

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top