如何使所有AJAX调用顺序?

时间:2009-07-20 03:26:48

标签: jquery ajax parallel-processing jquery-deferred sequential

我使用jQuery。而且我不希望在我的应用程序上进行并行AJAX调用,每个调用必须在开始之前等待之前的调用。怎么实现呢?有帮助吗?

UPDATE 如果有XMLHttpRequest或jQuery.post的任何同步版本,我想知道。但顺序!=同步,我想要一个异步和顺序的解决方案。

12 个答案:

答案 0 :(得分:16)

与使用同步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语言功能,所以这应该会给你一个很好的学习动力。

答案 1 :(得分:6)

你有两个我能想到的选择。一种是通过回调链接它们。另一种是使调用同步而不是异步。

您是否有理由要求它们顺序?这会减慢速度。

要使调用同步,您需要将Ajax调用中的async选项设置为false。请参阅http://docs.jquery.com/Ajax/jQuery.ajax#options上的文档(单击选项选项卡以查看它们)。

答案 2 :(得分:2)

您可以尝试使用叙述性javascript http://www.neilmix.com/narrativejs/doc/

我自己从未使用过它。如果我想这样做,我会设置某种抽象来链接异步操作。正如其他人所说,ajax对象的同步版本阻止事件在等待响应时被处理。这会导致浏览器在收到响应之前看起来已冻结。

答案 3 :(得分:1)

请注意: 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。

答案 4 :(得分:1)

你可以做到这一点的最好办法就是像诺斯雷德纳所说的那样链接回调。我不建议使用同步XMLHttpRequest,因为它们会锁定整个应用程序。

据我所知,没有太多帮助,但你可以做类似回调FIFO的事情。

答案 5 :(得分:1)

async 选项设置为false,例如

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

参考:Ajax/jQuery.ajax

答案 6 :(得分:1)

答案 7 :(得分:0)

同步调用不一定要慢一些,如果你有一个AJAX调用打开的应用程序,帖子,然后关闭套接字,多次调用套接字没有意义,因为一些套接字只能处理单个连接,在哪种情况下,排队数据使其仅在前一个AJAX调用完成时发送,意味着更高的数据吞吐量。

答案 8 :(得分:0)

(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. 使用jQuery ajax调用
  2. 请求3个json文件
  3. 按顺序(不是并行)处理await
  4. 适用于Chrome / Firefox / Edge(截至1/30/2018)
  5. 更多MDN

答案 9 :(得分:0)

您可以使用promise顺序进行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);

答案 10 :(得分:-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);

答案 11 :(得分:-1)

  

顺序!=同步,我想要一个异步和顺序解决方案

同步执行通常意味着“使用相同的时钟”,而顺序执行意味着“按顺序或顺序执行”。

对于您的特定用例,我认为必须满足这两个条件,因为异步执行意味着可能出现非顺序结果。