2009-07-20 5 views
21

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

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

+4

Вы знаете, что «А» в AJAX расшифровывается, правильно :-) –

+2

Это, безусловно, я sn't ответ, но это интересный признак хорошо продуманной структуры, когда * этот * является запутанным вопросом, а не как сделать его одновременным. :) –

+8

@Ed Swangren, да, но AJAX не должен быть асинхронным, JavaScript или XML. :-) – Nosredna

ответ

14

Там в гораздо лучший способ сделать это, чем при использовании синхронных вызовов Ajax. Jquery ajax возвращает отложенное значение, поэтому вы можете просто использовать цепочку соединений, чтобы удостовериться, что каждый вызов ajax заканчивается до следующего запуска. Вот пример работы с более подробным примером, который вы можете сделать play with on 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 для JavaScript, так что это даст вам хороший стимул для изучения.

+0

Эй, это немного поздно, но в любом случае: Большой ответ помог мне и работал как шарм. Но я действительно не понимаю, как это работает. Я пытался понять и прочитать документы, но это для меня загадка. –

+0

@DanLee Похоже, вы не единственный. –

+0

Трудно понять обещания javascript и способ, которым jquery реализует концепцию, не изучая ее ;-) Много документов. –

6

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

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

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

+0

Как сделать их синхронными? –

+0

Или третий вариант: класс, который будет управлять очередью запросов и обрабатывать их последовательно. –

+0

Я отредактировал свой ответ, чтобы указать на параметры Ajax. Установите для параметра async значение false. – Nosredna

1

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

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

EDIT: хорошо, с обновлением это ясно, что вы хотите достичь;)

Таким образом, ваш код может выглядеть следующим образом:

$.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

Я знаю ваше решение, но множественный запрос не генерируется одним и тем же, поэтому я не могу связать их вместе, как вы показали.Мое решение будет больше похоже на блокировку (globalAjaxObject) в C# –

1

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

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

2

Вы могли бы дать описательную Javascript попробовать http://www.neilmix.com/narrativejs/doc/

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

+1

Это выглядит круто. – Nosredna

+0

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

+0

Как я уже сказал, я не использовал NJS, но в его описании говорится, что он добавляет оператор yield, который просто прекращает выполнение функции до тех пор, пока не запущено событие. Мне кажется, что это не помешает параллелизму. Если бы это было так, это не было бы очень полезной библиотекой для всех. – Breton

3

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

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

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

+0

В ближайшее время параметр async будет удален из jQuery. –

+0

Это лучший ответ для первоначального запроса OP. Это предложение гарантирует минимальную сложность IOE (in-order-execution). Никогда не планировалось удалить флаг async из jquery, в отличие от того, что подразумевает @LS. – kamelkev

+1

Помните: «Начиная с jQuery 1.8, использование async: false с jqXHR ($ .Deferred) устарело, вы должны использовать параметры успешного/ошибочного/полного обратного вызова вместо соответствующих методов объекта jqXHR, таких как jqXHR.done() «. http://docs.jquery.com/Ajax/jQuery.ajax#options –

0

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

-1

Как насчет использования событий 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); 
0

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

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

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

0
(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 (по состоянию на 1/30/2018)

больше на MDN

 Смежные вопросы

  • Нет связанных вопросов^_^