Javascript 长时间运行的AJAX请求在几分钟后重新提交

Javascript 长时间运行的AJAX请求在几分钟后重新提交,javascript,jquery,ajax,Javascript,Jquery,Ajax,我有一个长时间运行的服务调用,我使用jQuery.ajax调用它。这项服务可能需要2分钟以上才能完成 AJAX请求已提交,不需要响应。一个单独的AJAX请求报告操作的进度 在一些站点上,我们发现代理在2分钟后重新提交Ajax请求本身。浏览器是Chrome,但我怀疑它是否与Chrome相关 这绝对不是我们重新提交ajax请求的情况。为了确保在beforeSend事件中设置bool以防止任何重新提交 我现在处理这种重新提交的方式是,如果在执行操作之前已经提交了nonce,则向数据请求和服务测试添加n

我有一个长时间运行的服务调用,我使用jQuery.ajax调用它。这项服务可能需要2分钟以上才能完成

AJAX请求已提交,不需要响应。一个单独的AJAX请求报告操作的进度

在一些站点上,我们发现代理在2分钟后重新提交Ajax请求本身。浏览器是Chrome,但我怀疑它是否与Chrome相关

这绝对不是我们重新提交ajax请求的情况。为了确保在beforeSend事件中设置bool以防止任何重新提交

我现在处理这种重新提交的方式是,如果在执行操作之前已经提交了nonce,则向数据请求和服务测试添加nonce。对该服务的任何第二次调用都将无害地返回,原始请求将继续进行

请注意,我添加了一个无意义的服务,它什么也不做,只是等待5分钟,而且我一次也没有遇到测试服务的问题(在生产站点上)

有人能给我一些线索来说明是什么导致了ajax的重新提交,以及如何在本地复制它吗

这是用于发送请求的js:

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;
    }
});
下面是从HTTP存档(HAR)请求的ajax,在该存档中请求被重新提交,但立即失败。注意2分钟的时间

{
"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"

如果请求总是在2分钟内得到处理,则表明服务器端(node.js)没有正确完成响应(使用
rsp.end()
)。2分钟是
express/node
服务器上的默认超时时间。

这里也有同样的情况。如果客户端到目前为止没有收到响应,jQuery显然会在120秒(默认超时)后重新发送请求

增加超时,如中所示:

    $.ajax({
      url: localhost,
      type: 'POST',
      timeout: 1000*60*10
这不会改变游戏。请求在2分钟后仍然重新发送,尽管客户端继续等待任何响应

虽然服务器端能够很好地并行处理这两个请求,但客户机请求在第一个请求的有效响应时失败

还没有解决办法

编辑:

事实证明,浏览器才是重新发送事件的那个,而且该行为完全符合HTTP/1.1规范。实际上,(node.js)后端在超时120秒后关闭了套接字,如jonasnas所指。解决方案是在响应对象上禁用超时,如中所示:

    // this is a long running request,
    // so disable response timeout
    response.setTimeout(0);
不幸的是,这里的所有其他(浏览器端)建议都不适合我。但是,只需让ajax请求立即超时即可完成以下任务:

这可以通过以下方式实现:

$.ajax("https://someurl/", {
  ...
  timeout:1
  ...
});
另请注意:将超时设置为0不起作用

如果服务器端的计算需要很长时间,那么在这里等待也没有意义。需要单独的解决方案来检查计算是否完成


这种方法看起来很糟糕。因此,任何更好的工作解决方案仍然受到高度欢迎;-)

移动评论以获得更高的可视性。 我们的问题是负载平衡器。当我们通过LB url从AJAX调用web api服务时,我们得到了120秒的问题,并且对服务进行了多次调用,没有来自客户端的代表性额外调用。 当我们通过直接服务器节点调用api时,从等式中删除负载平衡器,我们不会遇到问题。 如果等式中有负载平衡器,请调查直接调用服务器节点是否有效。如果是,请接合负载平衡器支架


作为一种临时解决方法,在LB问题解决之前,我将在页面加载时在一个隐藏字段中将服务器节点名称返回到客户端页面,并让我的JS代码使用该名称构建一个用于调用服务的直接URL。

您是否检查了在重新提交时是否实际调用了您的代码(ajax代码)。。。您可以添加
console.log()
stmt在ajax请求之前,并在
beforeSend
处理程序中检查这一点-如果您的代码确实发送了第二个请求,那么消息将在控制台中记录两次。下一步可以在ajax行中设置断点,查看是否调用了两次,以及是否查看要查看的堆栈跟踪如何/从何处启动第二个呼叫。。。或者您可以使用
console.trace()
日志来查看调用堆栈。我确定代码中重新提交的不是我的ajax请求。首先,重新提交不会作为单独的请求出现在Chromes network profiler中——如果代码只是重新执行,就会出现这种情况。beforeSend不会第二次执行。是的。。你是对的。。。在这种情况下,我不认为是客户端代码导致了它。。。。您必须重新查看服务器端代码…我不确定服务器中会出现什么问题。即使用户代理重新提交了请求,原始请求仍将继续执行。我试图指出重新提交请求的原因。后端是.net ASHX。我已经尝试过了,不认为这是服务器超时。ASHX将超时设置为小时,即使重新提交已完成或失败,线程仍将继续执行。对于jQuery超时,没有有效的全局超时,也没有为此实例指定超时。