当请求没有收到响应时会发生什么?我看到正在进行重试。

26

我想问的问题可能更多与浏览器相关,但这是一个非常基本的问题,在构建Web应用程序时,我想找到答案。

在我的客户端代码中,我正在进行一个$.ajax调用。这个POST请求可能需要一段时间才能响应。我看到的是在一定时间后,请求会再次发送。

我以为是我的$.ajax调用再次发送了它,但无论我在服务器上看到POST请求多少次,我只看到beforeSend回调函数被调用一次。我相当确定我的代码没有多次发送它,所以我认为这是浏览器重试的问题?

我知道我的服务器收到了多个请求,因为我打开了Wireshark并看到了多个POST请求。所以我的假设是这与HTTP有关吗?也就是说,如果在一定时间内没有接收到响应,则会重新发送请求?

下面是我的调用示例。

$.ajax({
                    async: false,
                    type: 'POST',
                    url: '<%= url_for('importDevice') %>',
                    data: { device: val },
                    retryLimit: 0,
                    //callback
                    success: function(data) {
                    alert('calling import');
                    if ( data == 'nomaster')
                    {
                            // Display a warning  toast, with a title
                            toastr.warning('You must set the Master Key first!', 'Warning');
                            $.ismasterset = false;
                            //reset the form contents after added
                    } else
                    {
                            $("div#content").html(data);
                    }
                    },
                     beforeSend: function(){
                    alert('in before send');
                    }
            });

这是所有相关代码,“retryLimit”没有被使用,我只是没有从我的代码中删掉它,并且是的,在我加入它之前问题就存在了。

用客户端和服务器的输出进行编辑。

好的,我安装了“Firefox的Live Http headers”。

在“Generator”标签中,我看到了一个单一的调用。

'#request# POST http://testhost/importdevice' 

虽然我没有在“headers”部分看到POST,但这可能是因为没有响应吧?

但是在我的Web服务器中,我看到了两个间隔约为22秒的调用。

[Sun Jan 13 03:08:45 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).

[Sun Jan 13 03:09:07 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).

我也可以在wireshark中看到这些相同的调用...

这就是为什么我问这是否是正常行为,尝试重新发送请求,如果没有收到响应,类似于TCP握手和SYN重传。

新更新

这似乎与我的Ajax调用无关。如果我创建一个带有简单HREF的按钮。

例如:

<a href="/importdevice?device=serverA" class="btn btn-success">TestDirect</a>

然后在我的“Live HTTP headers”输出中,我只得到一个实例。

#request# GET http://172.16.118.15/importdevice?device=serverA

但是我在服务器日志中再次收到了同样的信息。

[Sun Jan 13 03:20:25 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS  X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
[Sun Jan 13 03:20:48 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).

在服务器上使用Wireshark,我也看到了它出现了两次……并且正如预期的那样,我的服务器代码也被调用了两次……这真的让我很困惑。


2
那显然不是你真正的调用,因为它包含语法错误。请使用复制和粘贴。 - T.J. Crowder
retryLimit 属性在那里有什么作用?这是所有相关的代码吗? - Alexander
好的,我已经准确地剪切和粘贴了我的代码。这不会产生任何错误,URL已经被我的Web框架扩展出来。但是我已经使用直接的URL进行了测试,我遇到了同样的问题。 - user1768233
抱歉,“retryLimit”不相关。 - user1768233
2个回答

28
请查看这篇博客文章,解释了正在发生的事情:http://geek.starbean.net/?p=393 根据 HTTP/1.1 RFC 8.2.4
如果一个HTTP/1.1客户端发送一个包含请求主体的请求,但不包括带有“100-continue”期望的Expect请求头字段,并且如果客户端没有直接连接到HTTP/1.1源服务器,并且如果客户端在收到服务器的任何状态之前看到连接关闭,则客户端应重试该请求。
确保您设计您的Web应用程序以容忍这些额外的请求。如果您想让ajax请求只执行一次某些操作,例如将某些内容写入数据库,则需要将请求设计为幂等。请参见:什么是幂等操作? 此外,这突出了GET和POST操作之间的区别: http://www.cs.tut.fi/~jkorpela/forms/methods.html 作为一般的设计实践: - GET操作应该被设计为幂等的 - POST操作应该用于写入数据库等。

谢谢!那正是我想要的,而且还有更多! - user1768233
根据HTTP规范,即使是非幂等的请求,例如POST请求,客户端也可以重试。 - Yadu
@Yadu 是的,即使是POST请求也可以由客户端重试(正如问题提问者所经历的)。但是把所有POST请求都称为非幂等是不准确的。在某些情况下,人们可能希望将POST请求设计为幂等。请务必阅读此页面底部的最后一节,标题为“使用“POST”进行幂等查询的可能原因”。此页 - BigMacAttack
8
这个问题已经被标记为已回答,我猜它确实得到了回答,但是没有人明确说明除了在服务器端处理重复请求外我是否还可以采取其他措施。有没有办法告诉浏览器不要重新发送 POST 请求或禁用超时时间——最好是通过 JavaScript/ajax 来实现呢? - BoB3K
我现在有类似的问题。假设第一个请求发送到服务器,服务器需要3分钟来处理。2分钟后,第二个请求进来了。我的服务器会立即返回400。再过1分钟后,服务器将返回200(第一个请求已完成)。这样正确吗?目前的问题是客户端在获取400响应时显示错误。它不会等待200响应。 - Kaman Wu

0
为什么在请求不是异步的情况下设置回调函数?
如果您想要同步过程,请在调用之前放置beforeSend代码,然后在调用之后简单地放置success回调。
如果您想要异步方法,则设置async:true 此行代码也是错误的:
url: '<%= url_for('importDevice') %>',

看看引号:应该是这样的

url: '<%= url_for("importDevice") %>',

也许这些建议不能解决问题,但会指引你朝正确的方向去寻找。问题可能不在你发布的代码中,而是其他地方...

回到你的问题: 可能是浏览器的问题吗?我不确定,但谁知道会有什么奇怪的情况!!... 什么浏览器?你试过用其他浏览器吗?

我建议你尝试使用Firefox,并使用Live httpHeaders插件(非常容易设置和使用)。这样你就可以看到客户端发送的请求,而不是从服务器端接收到的响应。


谢谢Paolo,是的,我想要关闭异步。我的浏览器是Chrome,我也尝试过Safari并看到了相同的行为。在Chrome的开发工具中,我看到一个状态为“PENDING”的POST请求。然而,在我的服务器日志和Wireshark中,我看到POST请求被发送了两次。谢谢,我会安装Live httpHeaders插件,看看是否有帮助。 - user1768233
更新上面的内容。看起来与Ajax无关...现在我真的迷失了。 - user1768233

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接