【问题标题】:jQuery: how to make ajaxSend wait for another Ajax response before proceeding?jQuery:如何让 ajaxSend 在继续之前等待另一个 Ajax 响应?
【发布时间】:2015-09-18 03:41:27
【问题描述】:

我正在使用 jQuery (v.3.0.0),我需要 ajaxSend() 来检查 localStorage 中是否存在值,并将其添加到传出请求标头中。

如果localStorage 中不存在该值,ajaxSend() 应通过另一个 Ajax 请求获取该值,然后在标头中发送具有正确值的原始请求。

这必须是一个全局处理程序,适用于所有发出的 jQuery Ajax 请求。

让我们做一个代码示例。

$(document).ajaxSend(function (ev, req, opts) {
  // Before sending any jQuery Ajax request
  var original = req;
  if (localStorage.foo) {
    // If value "foo" is available, add it to the headers
    req.setRequestHeader('foo', localStorage.foo);
  } else {
    // Otherwise get it first, and add it to the headers
    $.get({url: '/foo', global: false})
      .done(function (data, textStatus, req) {
        // "foo" is received and added to the original request headers
        localStorage.foo = data;
        original.setRequestHeader('foo', data);
        // Now the original request is ready to be sent
      });
  }
});

foo不可用时,上面代码的问题是,很明显原始请求是在foo的值被检索之前发出的。

有没有办法解决这个问题并让它正常工作?

谢谢!!

【问题讨论】:

  • 你不能在第二个ajax调用中添加async: false吗?
  • 不,这会同时阻止一切,绝对不是一个好的选择。顺便说一句,jQuery.ajax() docs 中也提到了它,请查看:“强烈建议不要将此选项设置为 false(从而使调用不再异步),因为它可能导致浏览器无响应。”
  • 很抱歉,您试图将一个 ajax 调用包装在另一个 ajax 调用中,但这是行不通的
  • 嗯,这正是我要解决的问题。如果找到一种方法来控制 Ajax 调用的排队,那么它就可以解决。

标签: javascript jquery ajax asynchronous


【解决方案1】:

到目前为止,这是我能找到的最佳解决方案。它并不完美,也没有完全回答最初的问题,但它是一个很好的解决方法,并且非常接近我想要实现的目标。

主要区别在于它不是让原始请求等待,而是取消它,获取所需的值,然后创建一个与原始请求具有相同设置的新请求。

$(document).ajaxSend(function (ev, req, opts) {
  if (localStorage.foo) {
    // If value "foo" is available, add it to the headers
    req.setRequestHeader('foo', localStorage.foo);
  } else {
    // Otherwise cancel the original request, then get "foo",
    // and create a new request with the same settings as the original one
    req.abort();
    $.get({url: '/foo', global: false})
      .done(function (data, textStatus, req) {
        // "foo" is received
        localStorage.foo = data;
      })
      .then(function () {
        $.ajax(opts);
      });
  }
});

完美运行。如果有人找到了一个更好的解决方案,可以直接使用原始请求,我很乐意编辑这个答案并改进它。

谢谢!

【讨论】:

  • 您现在找到或可以提出更好的方法了吗?
【解决方案2】:

我认为您需要使用$.ajaxbeforeSend 选项,如果该值存在于localStorage 中,您可以从那里返回false 以停止请求。

这意味着您必须始终使用低级别的$.ajax 方法,也许您可​​以为$.get$.post$.getJSON 等制作自己的一组包装器。

【讨论】:

  • 谢谢马特!您能否发布您建议的方法的工作代码示例?干杯:)
  • 最终在没有 beforeSend 的情况下完成了它。您需要添加其他包装器,这也意味着您需要始终使用承诺风格的回调(即donefailalways 等)而不是使用参数回调,可能还有其他一些东西。
  • 嗨,马特,我查看了您的代码,但在我看来,这并没有处理所有传出的 jQuery Ajax 请求。我知道如何编写承诺或链式异步事件,尽管这不是我最初的问题。我错过了什么吗?
  • 对不起,这就是我所说的包装器,你必须修改你的代码才能使用包装器函数。这没什么大不了的,我已经做过几次了。我想不出任何其他方式抱歉。
  • 好的,我会等着看其他人是否提出了不同的解决方案,但同时感谢您的帮助,马特! :)
【解决方案3】:

我找到了一个不需要像 Pensierinmusica 的回答那样中止原始请求的解决方案。相反,原始 AJAX 调用的 xhr 对象的 send 方法被覆盖,然后可以稍后调用带有参数的原始发送,例如另一个 AJAX 请求完成。看到这个答案:https://stackoverflow.com/a/30263533

【讨论】:

  • 仅链接到其他答案会使此评论看起来很糟糕。我建议将此答案调整为添加一些实际代码并将其他答案链接为参考的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 2016-06-02
相关资源
最近更新 更多