【问题标题】:jQuery- are ajax responses received in order?jQuery-是否按顺序收到了 ajax 响应?
【发布时间】:2014-10-23 02:45:10
【问题描述】:

如果我有类似的东西:

var result;

var searchFunction = function(query) {
    $.ajax({
        url: '..',
        type: 'GET',
        data: {
            'query': query
        },
        success: function(result) {
            r = result
        }
    });
};

r 总是会成为最后一次searchFunction(query) 调用的结果吗?

例如,假设我这样做:

searchFunction('query1'); // this one takes 3 seconds to return because of internet delay
searchFunction('query2'); // this one takes 1 seconds to return because of less internet delay

我的r 会是'result1' 还是'result2'

由于它应该是异步 (AJAX),我希望 r = 'result1',但从我所做的一些测试中,我得到了 r = 'result2'

到底发生了什么?

【问题讨论】:

  • 一种方法是在发送新请求之前中止先前的请求...
  • 其实我想我知道如何解决这种并发问题,我只是想知道在这个特定的 web 案例中到底发生了什么。

标签: javascript jquery ajax asynchronous


【解决方案1】:

异步 ​​Ajax 调用可以按任意顺序返回。您不能依赖订单。您只能在完成处理程序中为特定的 Ajax 调用或在您调用的某些函数中可靠地使用 ajax 调用的结果,并将结果从完成处理程序传递给。

您绝对不希望将 ajax 结果放入全局变量中,然后尝试从那里使用它们。这是导致时间灾难的秘诀,绝不是编写代码的好方法。

如果你想协调多个 ajax 调用的结果,你可以自己做一堆自定义编码来按顺序跟踪结果,或者你可以使用 Async 或 Promise 等第三方库。


如果您要解决的实际问题是某种增量搜索,您可能同时有多个请求在进行中,并且您不想处理比您已有的请求更早的请求收到,那么您需要创建一个系统来跟踪排序,以便您知道何时忽略响应。有很多方法可以解决这个问题:

  1. 您可以在每次发送新请求时中止任何先前的请求。
  2. 您可以使用单调递增的数字标记每个请求,然后跟踪您迄今为止处理的最高响应编号,并忽略任何较低编号的响应。

仅供参考,如果您的服务器同步处理每个请求(因此它从第一个到达的请求开始,并且在第一个请求完成之前无法处理任何其他请求)并且一次只能处理一个请求,那么无论每个请求需要多长时间,它都可能仅以 FIFO 顺序返回结果。另一方面,如果您的请求处理是异步的,或者您的服务器可以一次处理多个请求,那么执行时间最短的请求将首先返回。

【讨论】:

  • 来自api.jquery.com/jquery.ajax "Ajax 中的第一个字母代表“异步”,意思是操作并行发生,不保证完成的顺序。"
  • 我实际上通过设置一个全局索引变量并在每个请求中递增它来解决“问题”,然后我将它复制到功能块中的一个局部变量,以便我可以在成功块(类似,但不如您的第二个解决方案那么优雅)。但也许我不清楚,我的问题不是并发问题是否存在以及如何解决,我的问题是“这个并发问题是否存在?”,因为我似乎无法重现它。当我手动执行这 2 个请求并在服务器中强制执行这些延迟时,result1 总是在 result2 之前返回。
  • 虽然我也很想知道如何实现你的两个解决方案。
  • @RodrigoRuiz - 您可以在此处看到该问题:jsfiddle.net/jfriend00/j11w8sbq - 回复以与发送的相反顺序返回。某些问题取决于服务器中的实现。如果服务器一次只同步处理一个请求,那么它可能会按照请求的顺序返回结果。但是,在多请求服务器或节点等异步架构中,第一个完成的请求是第一个返回的。
  • 我会接受你的回答,因为我认为这可能是因为我在 Heroku 中只有一个 dyno,所以可能是同步服务器,但请在你的回答中添加最后一条评论。跨度>
【解决方案2】:

您设置的r 是什么?无论如何,您不能期望 AJAX(定义为异步)以任何顺序发生。如果您要进行多次调用,并且想要存储所有响应,则需要执行以下操作:

var resultSet = [];

var searchFunction = function(query) {
    $.ajax({
        url: '..',
        type: 'GET',
        data: {
            'query': query
        },
        success: function(result) {
            resultSet.push(result);
        }
    });
};

【讨论】:

  • 实际上 r 只是我简化它的方式,我实际上所做的是用该结果重新填充表格。另外我知道我不应该期望响应中有任何顺序,但是为什么它们以我发送的相同顺序返回?即使有不同的延迟......
【解决方案3】:

AJAX 响应将按照响应到达的顺序进行处理。它们发送的顺序无关紧要。我已经修改了您的代码以记录响应,您可以在 Javascript 控制台中看到首先处理快速查询。

var searchFunction = function(query, delay) {
    $.ajax({
        url: '/echo/json/',
        type: 'POST',
        data: {
            json: JSON.stringify(query),
            delay: delay
        },
        success: function(r) {
            console.log(r);
        }
    });
};

searchFunction('query1', 3);
searchFunction('query2', 1);

jsfiddle demo

【讨论】:

  • 嗯,我不知道 '/echo/json/' 是什么(抱歉我的无知),但在我的真实服务器中不是这样(延迟实际上是在服务器中由于数据库访问)。
  • /echo/json/ 是 jsfiddle 上的一个 AJAX 服务器,用于测试 AJAX。在您的实际应用程序中,可能数据库中的某些内容正在序列化两个查询,因此快速查询正在等待慢速查询完成。
猜你喜欢
  • 1970-01-01
  • 2016-08-14
  • 2018-05-16
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多