【问题标题】:How to force one AJAX request to wait to finish for another?如何强制一个 AJAX 请求等待另一个完成?
【发布时间】:2014-10-19 15:03:08
【问题描述】:

我正在开发一款使用大量 AJAX 调用来更新、保存、编辑保存游戏等的游戏。

事情是,随后启动的 AJAX 请求似乎没有像我想要的那样排队。

例如,我正在检查服务器端是否允许执行某项操作,因此我需要当前保存的游戏。保存游戏之前发送,但检查请求在保存游戏请求完成之前执行。

所以我希望它是这样的:

AJAX start: Save Game
AJAX finish: Save Game
AJAX start: Check
AJAX finish: Check
AJAX start: Save Game
AJAX finish: Save Game

目前更像这样:

AJAX start: Save Game
AJAX start: Check
AJAX finish: Save Game
AJAX start: Save Game
AJAX finish: Check
AJAX finish: Save Game

即使 AJAX 调用按正确的顺序触发。他们只需要等到之前触发的调用完成。

有没有办法在全球范围内实现这一目标?因为问题是大多数调用都不知道其他请求。

我可以在不调用setInterval 来检查请求是否完成的情况下完成这项工作吗?

更新:显然,我并没有解决实际问题。我知道这是因为 AJAX 是异步的。

但我需要那些留在队列中。同样在运行时,我不知道什么时候触发了哪些调用,因为这完全取决于用户操作。所以我无法在save 请求之后调用check 请求,因为我不知道用户是否触发了需要调用check 请求的操作。

所以我需要一个全局实现,其中 ajax 请求总是等待它们的执行,直到预先存在的每个请求都完成。

所以我希望这些调用是异步的(不冻结 UI 等),但在执行顺序方面“同步”。

【问题讨论】:

  • 是的。在第一个的回调中设置下一个请求。
  • 这是因为ajax请求的异步性...
  • 使用从 ajax 调用返回的promises。您可以根据需要并行或顺序或组合运行任何数量。 使用回调会在代码中引入你可能不想要的依赖关系。
  • 正如更新版本和 Praveen Kumars 回答下方的评论所暗示的那样:我基本上想要一个请求来检查,如果当前有请求正在运行。如果不是,则触发请求,如果是,则该请求应等待所有其他请求完成。

标签: javascript jquery ajax asynchronous


【解决方案1】:

有一个非常有用的 jquery 插件 ajaxQ 可以让你创建一个 ajax 请求队列

$.ajaxq ("MyQueue", {
    url: 'http://jsfiddle.net/echo/jsonp/',
    type: 'post',
    dataType: "jsonp"
});

在我看来,最好为自己创建一个添加到队列的函数,如下所示:

function AddRequest(name, url, postData) {
var jqXHR = $.ajaxq(name, {
    url: url,
    type: 'POST',
    contentType: "application/x-www-form-urlencoded",
    data: postData,
    beforeSend: function () {
        //do stuff
    },
    error: function (response) {
        //do stuff
    },
    complete: function (response) {
        //do stuff
    },
    success: function (response) {
        //do stuff
    }
});
}

然后你可以这样调用:

var myurl = "http://www.example.com/myaction";
var postData = "myparam1=one&myparam2=two";
AddRequest('myAjaxQueue', myurl, postData);

【讨论】:

  • 几个月前这让我很难受,这个解决方案为我解决了这个问题,很高兴我能提供帮助!
【解决方案2】:

如果您正在使用 jQuery 的 $.ajax()$.post()$.get(),请使用回调开始下一个!例如:

console.log("AJAX start: Save Game");
$.post("save-game.php", function(){
    console.log("AJAX finish: Save Game");
    console.log("AJAX start: Check");
    $.post("check.php", function(){
        console.log("AJAX finish: Check");
        // Iterate from here using a recursive function! :P
    });
});

你可以做迭代,可能是这样:

function saveCheckGame()
{
    console.log("AJAX start: Save Game");
    $.post("save-game.php", function(){
        console.log("AJAX finish: Save Game");
        console.log("AJAX start: Check");
        $.post("check.php", function(){
            console.log("AJAX finish: Check");
            saveCheckGame();
        });
    });
}

【讨论】:

  • 我不能这样做,因为调用是由用户交互触发的。这可以是很多很多不同的地方。所以这些调用必须保持独立。
  • @JohannesKlauß 那么,您能否使用$.ajaxComplete 方法检查AJAX 调用是否完成,然后继续下一个?
  • 不是真的,因为不知道有没有下一个。我基本上想要一个请求来检查,如果当前有请求正在运行。如果不是,则触发请求,如果是,则该请求应等待所有其他请求完成。
  • 啊! Grr...我放弃了。我需要想办法做到这一点! :)
【解决方案3】:

一种方法是使用第一个请求的回调来启动下一个。

更简洁的解决方案是在回调中设置一个事件,并在事件触发时运行第二个请求。

在第一次请求回调中

$( document ).trigger( "request1Finished" );

附加事件处理程序

$( document ).on( "request1Finished", function() {
    // run next request
});

【讨论】:

    【解决方案4】:

    Here你可以找到一个有趣的方面 async ajax 调用。但我认为您应该为您的场景考虑jQuery .promise()。它具有等待和执行的能力。您可以在docs找到更多详细信息。

    阅读thisjQuery ajax docs。这个博客包含一个关于how to use延迟承诺的好例子。

    【讨论】:

      猜你喜欢
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 2016-12-12
      相关资源
      最近更新 更多