I have a long running service call, that I call using jQuery.ajax. The service can take well over 2 minutes to complete.
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.com/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.com/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",
"compression": 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"
Use setInterval() when you want to send AJAX request at a particular interval every time and don't want to depend on the previous request is completed or not. But if you want to execute the AJAX when the previous one is completed then use the setTimeout() function.
}); If isLoading is false, the AJAX call starts, and we immediately change its value to true. Once the AJAX response is received, we turn the value of that variable back to false, so that we can stop ignoring new clicks.
Reducing the number of requests performed, and the amount of data included in both sides of the transaction, will have a dramatic impact on your Ajax performance. Making server changes will help, too, but may be beyond your control.
JIRA has a default AJAX timeout period so that requests in the browser do not run for unlimited amounts of time. Normally 30 seconds is plenty of time for a typical data request. AJAX timeouts can be caused by many different things.
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 compliant 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 you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With