admin管理员组

文章数量:1429993

I'm using jQuery (v.3.0.0) and I need ajaxSend() to check if a value is present in localStorage, to add it in the outgoing request headers.

If the value is not present in localStorage, ajaxSend() should get this value with another Ajax request and then send the original request with the correct value in the headers.

This must be a global handler, that applies to all jQuery Ajax requests that are sent out.

Let's make a code example.

$(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
      });
  }
});

When foo is not available, the problem with the code above is that obviously the original request is sent out before the value of foo is retrieved.

Is there any way to fix this and get it to work properly?

Thanks!!

I'm using jQuery (v.3.0.0) and I need ajaxSend() to check if a value is present in localStorage, to add it in the outgoing request headers.

If the value is not present in localStorage, ajaxSend() should get this value with another Ajax request and then send the original request with the correct value in the headers.

This must be a global handler, that applies to all jQuery Ajax requests that are sent out.

Let's make a code example.

$(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
      });
  }
});

When foo is not available, the problem with the code above is that obviously the original request is sent out before the value of foo is retrieved.

Is there any way to fix this and get it to work properly?

Thanks!!

Share Improve this question edited Sep 18, 2015 at 4:38 Pensierinmusica asked Sep 18, 2015 at 3:41 PensierinmusicaPensierinmusica 7,07810 gold badges44 silver badges60 bronze badges 4
  • Can't you add async: false to the second ajax call? – Maria Ines Parnisari Commented Sep 18, 2015 at 3:45
  • No, that would block everything in the meantime and is definitely not a good choice. Btw, it's also mentioned in the jQuery.ajax() docs, check it out: "Setting this option to false (and thus making the call no longer asynchronous) is strongly discouraged, as it can cause the browser to bee unresponsive." – Pensierinmusica Commented Sep 18, 2015 at 3:48
  • Well i'm sorry but you're trying to wrap one ajax call inside another ajax call and that's not going to work – Maria Ines Parnisari Commented Sep 18, 2015 at 3:49
  • Well, that's exactly what I'm trying to solve. If one finds a way control the queuing of Ajax calls then it can be solved. – Pensierinmusica Commented Sep 18, 2015 at 3:50
Add a ment  | 

3 Answers 3

Reset to default 4

So far, this is the best solution that I could find. It's not perfect, and it does not exactly answer the original question, but it's a good workaround and gets very close to what I was trying to achieve.

The main difference is that instead of making the original request wait, it cancels it, it gets the desired value, and then it creates a new request with the same settings as the original one.

$(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);
      });
  }
});

It works perfectly. If someone finds out a better solution that allows to directly use the original request I'll be happy to edit this answer and improve it.

Thanks!

I think you need to use the beforeSend option of $.ajax, you can return false from there if the value is present in localStorage in order to stop the request.

This will mean you always have to use the low-level $.ajax method, perhaps you could make your own set of wrappers for $.get, $.post, $.getJSON etc.

I found a solution that does not need to abort the original request as in Pensierinmusica's answer. Instead the send method of the xhr object of the original AJAX call is overridden, and the original send with arguments can then be invoked later when e.g. another AJAX request pletes. See this answer: https://stackoverflow./a/30263533

本文标签: javascriptjQuery how to make ajaxSend wait for another Ajax response before proceedingStack Overflow