admin管理员组

文章数量:1296317

I have a long running service call, that I call using jQuery.ajax. The service can take well over 2 minutes to plete.

The AJAX request is submitted, and no response is expected. A separate AJAX request reports on the progress of the operation.

On some sites, we have found is that after 2 minutes the agent resubmits the Ajax request itself. The browser is Chrome, but I doubt its a Chrome related issue.

This definitely is not a case of us resubmitting the ajax request. To be sure we set a bool to prevent any re-submission in the beforeSend event.

The way I am handling now handling this re-submission, is by adding a nonce to the data request and the service tests if the nonce has already been submitted prior to carrying out its operation. Any second call to this service harmlessly returns and the original request continues to progress.

Note that I added a pointless service that does nothing but waiting for 5 minutes, and not once have I experienced the problem with the test service (on the production sites).

Can anyone give me any clues to what is causing this ajax re-submission, and how to go about reproducing it locally?

This is the js used to send the request:

var sent = false;
var data = { ... }; // data is a very large object;

$.ajax("service.ashx?loc=area/subarea/", {
    type: "POST",
    data: data,
    traditional: true,
    error: function (jqXHR, textStatus, errorThrown) {
        if (jqXHR.status === 0) {
            // see 

        } else {
            ReportFailure(textStatus,errorThrown);
        }
    },
    beforeSend: function () {
        if (sent === true) {
            return false;
        }
        sent = true;
        return true;
    }
});

Here is the ajax requested from a HTTP archive (HAR) where the request was re-submitted and it instantly failed. Notice the 2 minute time.

{
"startedDateTime": "2015-12-11T12:26:58.018Z",
"time": 120066.61499999973,
"request": {
  "method": "POST",
  "url": ".ashx?loc=area/subarea/",
  "httpVersion": "HTTP/1.1",
  "headers": [
    ... // removed for brevity
  ],
  "queryString": [
    { "name": "loc", "value": "area/subarea/" }
  ],
  "cookies": [
    ... // removed for brevity
  ],
  "headersSize": 1163,
  "bodySize": 48048,
  "postData": {
    "mimeType": "application/x-www-form-urlencoded; charset=UTF-8",
    "text": ..., // removed for brevity
    "params": [
      ... // removed for brevity        ] }
},
"response": {
  "status": 500,
  "statusText": "Internal Server Error",
  "httpVersion": "HTTP/1.1",
  "headers": [
    {
      "name": "Date",
      "value": "Fri, 11 Dec 2015 12:28:57 GMT"
    },
    ... // removed for brevity
  ],
  "cookies": [],
  "content": {
  "size": 54,
  "mimeType": "text/xml",
  "pression": 0
  },
  "redirectURL": "",
  "headersSize": 305,
  "bodySize": 54,
  "_transferSize": 359
},
"cache": {},
"timings": {
  "blocked": 120005.055999998,
  "dns": -1,
  "connect": -1,
  "send": 1.0939999989932403,
  "wait": 59.986000001008506,
  "receive": 0.47900000172376167,
  "ssl": -1
},
"connection": "7498"

I have a long running service call, that I call using jQuery.ajax. The service can take well over 2 minutes to plete.

The AJAX request is submitted, and no response is expected. A separate AJAX request reports on the progress of the operation.

On some sites, we have found is that after 2 minutes the agent resubmits the Ajax request itself. The browser is Chrome, but I doubt its a Chrome related issue.

This definitely is not a case of us resubmitting the ajax request. To be sure we set a bool to prevent any re-submission in the beforeSend event.

The way I am handling now handling this re-submission, is by adding a nonce to the data request and the service tests if the nonce has already been submitted prior to carrying out its operation. Any second call to this service harmlessly returns and the original request continues to progress.

Note that I added a pointless service that does nothing but waiting for 5 minutes, and not once have I experienced the problem with the test service (on the production sites).

Can anyone give me any clues to what is causing this ajax re-submission, and how to go about reproducing it locally?

This is the js used to send the request:

var sent = false;
var data = { ... }; // data is a very large object;

$.ajax("service.ashx?loc=area/subarea/", {
    type: "POST",
    data: data,
    traditional: true,
    error: function (jqXHR, textStatus, errorThrown) {
        if (jqXHR.status === 0) {
            // see http://stackoverflow./questions/3825581/does-an-http-status-code-of-0-have-any-meaning

        } else {
            ReportFailure(textStatus,errorThrown);
        }
    },
    beforeSend: function () {
        if (sent === true) {
            return false;
        }
        sent = true;
        return true;
    }
});

Here is the ajax requested from a HTTP archive (HAR) where the request was re-submitted and it instantly failed. Notice the 2 minute time.

{
"startedDateTime": "2015-12-11T12:26:58.018Z",
"time": 120066.61499999973,
"request": {
  "method": "POST",
  "url": "https://example./service.ashx?loc=area/subarea/",
  "httpVersion": "HTTP/1.1",
  "headers": [
    ... // removed for brevity
  ],
  "queryString": [
    { "name": "loc", "value": "area/subarea/" }
  ],
  "cookies": [
    ... // removed for brevity
  ],
  "headersSize": 1163,
  "bodySize": 48048,
  "postData": {
    "mimeType": "application/x-www-form-urlencoded; charset=UTF-8",
    "text": ..., // removed for brevity
    "params": [
      ... // removed for brevity        ] }
},
"response": {
  "status": 500,
  "statusText": "Internal Server Error",
  "httpVersion": "HTTP/1.1",
  "headers": [
    {
      "name": "Date",
      "value": "Fri, 11 Dec 2015 12:28:57 GMT"
    },
    ... // removed for brevity
  ],
  "cookies": [],
  "content": {
  "size": 54,
  "mimeType": "text/xml",
  "pression": 0
  },
  "redirectURL": "",
  "headersSize": 305,
  "bodySize": 54,
  "_transferSize": 359
},
"cache": {},
"timings": {
  "blocked": 120005.055999998,
  "dns": -1,
  "connect": -1,
  "send": 1.0939999989932403,
  "wait": 59.986000001008506,
  "receive": 0.47900000172376167,
  "ssl": -1
},
"connection": "7498"
Share Improve this question asked Dec 14, 2015 at 11:23 Drew WilliamsDrew Williams 6376 silver badges14 bronze badges 8
  • Did you check whether your code(ajax code) is actually getting called when the resubmit is happening... you can add a console.log() stmt before the ajax request and in the beforeSend handlers to check this - if your code is really sending the second request then the messages will get logged twice in the console – Arun P Johny Commented Dec 14, 2015 at 11:27
  • the next step could to either put a break point in the ajax line to see whether it is getting called twice and if see the stack trace to see how/where the second call is initiated from... or you can use the console.trace() logging to see the call stack – Arun P Johny Commented Dec 14, 2015 at 11:28
  • I'm certain its not my ajax request being resubmitted in code. For one the re-submission doesn't appear as a separate request in Chromes network profiler - which it would if the code was simply re-executed. beforeSend isn't executed a 2nd time. – Drew Williams Commented Dec 14, 2015 at 11:57
  • yes.. you are right... in that case I don't think it is the client side code that is causing it.... you will have to relook at your server side code... – Arun P Johny Commented Dec 14, 2015 at 11:59
  • I'm not sure what the problem in the server would be. The original request continues to execute even when the user agent has resubmitted the request. I'm trying to pin point why the request is resubmitted. – Drew Williams Commented Dec 18, 2015 at 9:35
 |  Show 3 more ments

4 Answers 4

Reset to default 4

Same story here. jQuery obviously resends a request after 120 seconds (the default timeout) if no response has been received by the client so far.

Increasing the timeout as in:

    $.ajax({
      url: localhost,
      type: 'POST',
      timeout: 1000*60*10

doesn't change the game. Request still resends after 2 minutes, although the client continues to wait for any response.

although the server side is able to handle these two requests in parallel nicely, the clients request failes on valid response of the first request.

no solution yet

EDIT:

it actualy turned out, that the browser is the one, that resends the event and that behavior is fully pliant with HTTP/1.1 specs. And actualy the (node.js) backend closed the socket after a timeout of 120 seconds, such as jonasnas pointed to. The solution was to disable timeout at the response object, as in:

    // this is a long running request,
    // so disable response timeout
    response.setTimeout(0);

If request is handled always in 2min its an indication that your server side (node.js) is not finishing the response properly (with rsp.end()). 2 minutes is the default timeout on the express/node server.

Unfortunately, all other (browser-side) remendations here did not work out for me. However, simply letting the ajax request timeout immediately does the job:

This can be achieved with:

$.ajax("https://someurl/", {
  ...
  timeout:1
  ...
});

As as side note: Setting timeout to 0 does not work.

If the server side putation takes so long, it does not make sense to wait here anyway. A separate solution is required to check the putation for pletion.

This approach looks awful. So, any better working solutions are still highly wele ;-)

Our issue was a load balancer. When we called the web api service from AJAX via the LB url, we get the 120 second issue, and repetetive calls to the service, with no representative extra calls from the client. When we call the api via a direct server node, removing the load balancer from the equation, we don't suffer the issue. If a load-balancer is in your equation, investigate if calling direct to server node works. If so, engage load balancer support.

As an interim workaround, until LB issue is solved, I will return the server node name to the client page on page load in a hidden field, and have my JS code use this to construct a direct URL for calling the service.

本文标签: javascriptLong running AJAX request resubmits after a couple of minutesStack Overflow