【问题标题】:JQuery Execution Order of Deferred Object Callback Hooks (Promise vs. Complete)延迟对象回调挂钩的 JQuery 执行顺序(承诺与完成)
【发布时间】:2017-11-29 14:29:30
【问题描述】:

我有一个本地托管的项目,其视图向服务器发出 AJAX 请求。代码在this jsfiddle 中重复,没有 URL 和数据参数,这些参数被替换为 jsfiddle 测试数据以模拟 AJAX 请求。

(function demo(iteration) {
    count = iteration || 0;
  
  if (count < 3) {
    $.when(testPromise(count).promise())
        .done(function () {
        doSomething();
        })
      .always(function () {
        demo(count + 1);
        });
  }
})();

function doSomething() {
    console.log("something!");
}

function testPromise(iteration) {
  var deferred = $.ajax({
    type: 'POST',
    url: '/echo/json/',
    data: {
      json: JSON.stringify({ "data": "Data!" }),
      delay: 0.1
    },
    dataType: 'json',
    beforeSend: function () {
            console.log("Before Send: " + iteration);
    },
    success: function(response) {
      console.log("Success: " + iteration);
    },
    error: function() {
        console.log("Error: " + iteration);
    },
    complete: function () {
        console.log("Complete: " + iteration);
    }
  });
  
  return deferred;
}

现在,Jsfiddle 执行以下打印语句:

但是,我的本地代码创建了一组替代打印语句:

你会注意到jsfiddle连续的AJAX请求是按顺序发出和完成的,但是本地输出显示连续的请求是在前一个完成之前发出的:Before Send: 1;完成:0发送前:2;完成:1。也就是说,这两种环境的 Promise 回调和 Complete 回调的处理顺序不同。

根据http://api.jquery.com/jquery.ajax/

$.ajax() 提供的回调钩子如下:

  1. beforeSend 回调选项被调用。
  2. 错误...
  3. 数据过滤器 ...
  4. 如果请求成功,则调用成功回调选项。
  5. Promise 回调 - .done()、.fail()、.always() 和 .then() - 按照注册的顺序被调用。
  6. 完成回调选项在请求完成时触发,无论是失败还是成功。

除了列表顺序之外,文档并没有真正说明这些回调的顺序是否得到保证,我认为由于 jsfiddle 和我的本地代码不协调,因此实际上不能保证顺序。

那么在幕后发生了什么会产生这两种不同的结果?假设我希望我的本地代码表现得像 jsfiddle(在 Promise 之前完成处理)——我可以做些什么改变来完成这个?

提前致谢 -

作为旁注,我知道以下 $.when() 功能可以通过 AJAX .complete() 处理程序实现。我故意使 AJAX 函数与需要调用它的条件无关,因为我的最终目标是制作一个通用的队列模块,它将处理队列处理并在必要时调用给定的可延迟函数。因此,我无法为此目的使用 AJAX .complete() 方法。

$.when(testPromise(count).promise())
    .done(function () {
        doSomething();
    })
    .always(function () {
        demo(count + 1);
    });

【问题讨论】:

  • ajax 是异步的。服务器可能会影响接收响应的顺序,这可能是您在 jsfiddle 中获得与您自己的服务器不同的结果的原因。
  • 确实如此,尽管我不希望服务器响应在这种情况下很重要,因为每个后续请求都依赖于已解决的前一个请求的延迟对象。因此,在任何给定时间,b/c 只有一个 ajax 请求具有“待处理”的延迟对象状态,服务器应该是无关紧要的。如果我错了,请纠正我,但我感谢您的意见!
  • 如果是这种情况,那么是的,服务器的响应将是无关紧要的。您能否提供问题中的相关代码?
  • 一切都在那个jsfiddle中
  • 假设两个位置都使用相同版本的 jquery,我无法解释为什么在这种情况下一个会给出与另一个不同的结果。

标签: jquery ajax jquery-deferred


【解决方案1】:

jQuery Deferred 已在 3.0 版 (https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/) 中更新,因此确保您的 jQuery 版本与小提琴 (3.2.1) 上的版本相同可能会有所帮助。

【讨论】:

  • 嗯,是的——我没想到版本控制会成为问题,因为延迟对象文档没有提到从 2.X 到 3.X 的机制变化,但你是绝对正确的。我的环境是 2.2,当我将 jsfiddle 降到 2.4 时,它的行为与我的本地代码库完全一样。傻我。感谢回复
猜你喜欢
  • 2015-12-23
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 2023-03-21
相关资源
最近更新 更多