jQuery 如何使所有 AJAX 调用按顺序进行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1151598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 10:46:38  来源:igfitidea点击:

How to make all AJAX calls sequential?

jqueryajaxparallel-processingjquery-deferredsequential

提问by Jader Dias

I use jQuery. And I don't want parallel AJAX calls on my application, each call must wait the previous before starting. How to implement it? There is any helper?

我使用 jQuery。而且我不希望在我的应用程序上进行并行 AJAX 调用,每次调用都必须在开始之前等待前一个调用。如何实施?有帮手吗?

UPDATEIf there is any synchronous version of the XMLHttpRequest or jQuery.post I would like to know. But sequential != synchronous, and I would like an asynchronous and sequential solution.

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

采纳答案by Todd Chaffee

There's a much better way to do this than using synchronous ajax calls. Jquery ajax returns a deferred so you can just use pipe chaining to make sure that each ajax call finishes before the next runs. Here's a working example with a more in depth example you can play with on jsfiddle.

有比使用同步 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.

            });

    });

}

Some people have commented they have no clue what the code does. In order to understand it, you first need to understand javascript promises. I am pretty sure promises are soon to be a native javascript language feature, so that should give you a good incentive to learn.

有些人评论说他们不知道代码的作用。为了理解它,您首先需要了解 javascript 承诺。我很确定 promises 很快就会成为原生 javascript 语言功能,所以这应该会给你一个很好的学习动力。

回答by Nosredna

You have two choices that I can think of. One is to chain them through callbacks. The other is to make the calls synchronous rather than async.

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

Is there a reason you want them sequential? That will slow things down.

您是否有理由希望它们按顺序排列?那会让事情变慢。

To make the call synchronous, you'll set the async option in the Ajax call to false. See the documentation at http://docs.jquery.com/Ajax/jQuery.ajax#options(click options tab to see them).

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

回答by Breton

You could give narrative javascript a try http://www.neilmix.com/narrativejs/doc/

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

I've never used it myself though. If I wanted to do this, I would setup some kind of abstraction for chaining asynchronous actions. As others have said, the synchonous version of the ajax object blocks events from being processed while it's waiting for a response. This causes the browser to look like it's frozen until it recieves a response.

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

回答by Joe Chung

Set the asyncoption to false, e.g.,

async选项设置为 false,例如,

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

Reference: Ajax/jQuery.ajax

参考:Ajax/jQuery.ajax

回答by FWH

Look at this: http://docs.jquery.com/Ajax/jQuery.ajax(click on the "options" tab).

看这个: http://docs.jquery.com/Ajax/jQuery.ajax(单击“选项”选项卡)。

But remember a synchronous call will freeze the page until the response is received, so it can't be used in a production site, because users will get mad if for any reason they have to wait 30 seconds with their browser frozen.

但请记住,同步调用将冻结页面,直到收到响应为止,因此不能在生产站点中使用它,因为如果出于某种原因,用户必须在浏览器冻结的情况下等待 30 秒,他们会生气。

EDIT: ok, with your update it's clearer what you want to achieve ;)

编辑:好的,随着您的更新,您想要实现的目标更清晰;)

So, your code may look like this:

因此,您的代码可能如下所示:

    $.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);
            });
        });
    });

This way, the second call will only be issued when the response to the first call has been received and processed, and the third call will only be issued when the response to the second call has been received and processed. This code is for getJSON but it can be adapted to $.ajax.

这样,只有在收到并处理了第一个调用的响应后才会发出第二个调用,只有在收到并处理了第二个调用的响应后,才会发出第三个调用。此代码用于 getJSON,但它可以适用于 $.ajax。

回答by Gab Royer

The best way you could do this is by chaining callbacks as Nosredna said. I wouldn't recommend using synchronous XMLHttpRequest as they lock your entire application.

最好的方法是按照 Nosredna 的说法链接回调。我不建议使用同步 XMLHttpRequest,因为它们会锁定您的整个应用程序。

There aren't much helper for this as far as I know, but you could do something resembling a callback FIFO.

据我所知,这方面的帮手并不多,但您可以做一些类似于回调 FIFO 的事情。

回答by Rm558

(async () => { 
  for(f of ['1.json','2.json','3.json']){
    var json = await $.getJSON(f);
    console.log(json)
 };
})()
  1. requests 3 json files with jQuery ajax calls
  2. process in sequence (not in parallel) with await
  3. works in Chrome/Firefox/Edge (as of 1/30/2018)
  1. 使用 jQuery ajax 调用请求 3 个 json 文件
  2. 使用 await 按顺序(非并行)处理
  3. 适用于 Chrome/Firefox/Edge(截至 2018 年 1 月 30 日)

more at MDN

更多在MDN

回答by Muthu Kumar

You can use promise to make ajax calls sequential. Using Array push and pop promise method, sequential ajax calls will be lot easier.

您可以使用 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);

回答by tomski777

Synchronous calls aren't necessarily slower, if you have an app where AJAX calls open, posts to, then closes a socket, multiple calls to the socket don't make sense as some sockets can only handle a single connection, in which case, queuing data so its only sent when the previous AJAX call has completed means much higher data throughput.

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