jQuery:如何让ajaxSend在继续之前等待另一个Ajax响应?

时间:2015-09-18 03:41:27

标签: javascript jquery ajax asynchronous

我正在使用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的值之前发送了原始请求。

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

谢谢!

3 个答案:

答案 0 :(得分: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);
      });
  }
});

完美无缺。如果有人发现一个更好的解决方案,允许直接使用原始请求,我将很乐意编辑此答案并进行改进。

谢谢!

答案 1 :(得分:0)

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

这意味着您总是必须使用低级$.ajax方法,也许您可​​以为$.get$.post$.getJSON等创建自己的包装器

答案 2 :(得分:0)

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