Как сделать все вызовы AJAX последовательными? - PullRequest
23 голосов
/ 20 июля 2009

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

ОБНОВЛЕНИЕ Если есть какая-либо синхронная версия XMLHttpRequest или jQuery.post, которую я хотел бы знать. Но последовательный! = Синхронный, и я хотел бы асинхронного и последовательного решения.

Ответы [ 12 ]

16 голосов
/ 27 сентября 2012

Есть гораздо лучший способ сделать это, чем использовать синхронные вызовы 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, так что это должно дать вам хороший стимул для изучения.

6 голосов
/ 20 июля 2009

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

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

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

2 голосов
/ 20 июля 2009

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

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

1 голос
/ 26 апреля 2011

И, кажется, теперь у вас есть решение для этого:

http://api.jquery.com/category/deferred-object/

или

http://www.slideshare.net/furf/making-ajax-sexy-jsconf-2010?from=ss_embed

1 голос
/ 20 июля 2009

Установите для параметра async значение false, например,

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

Ссылка: Ajax / jQuery.ajax

1 голос
/ 20 июля 2009

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

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

1 голос
/ 20 июля 2009

Посмотрите на это: 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.

0 голосов
/ 12 мая 2019

Вы можете использовать обещание для последовательных вызовов ajax. Используя метод массива push и pop обещание, последовательные вызовы 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);
0 голосов
/ 12 января 2018
(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.2008)

больше на MDN

0 голосов
/ 18 июня 2016

последовательный! = Синхронный, и я хотел бы асинхронного и последовательного решения

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

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

...