jquery ajax GET请求执行两次
Posted
技术标签:
【中文标题】jquery ajax GET请求执行两次【英文标题】:jquery ajax GET request executing twice 【发布时间】:2013-03-08 03:16:48 【问题描述】:我有以下通过单击按钮执行的 ajax 请求:
<a href="javascript:test()"><img src="css/images/test.png"></a>
function test()
console.debug("*");
$.ajax(
type: "GET",
dataType: "json",
url: '/path/to/url',
success: function(data)
console.debug("**");
,
error: function(jqXHR, status, error)
console.debug("*** " + status + " : " + error + " : " + jqXHR.status);
,
cache: false
);
请求响应大约需要 30 秒才能返回。但是,从 apache 日志可以看出,服务器两次接收并执行请求。请求的时间戳相隔 30 秒,但请求是相同的(例如 ?_=1363692320782)。点击响应函数被调用一次,错误回调被调用一次(在初始请求后正好 60 秒),尽管 apache 响应是 200。
此问题已在 Samsung Galaxy S2,android 版本 2.3.5 的 phonegap 应用程序中重现。
更新 - 从下面的评论中添加 Apache 日志条目
1.2.3.4 - - [19/Mar/2013:14:07:59 +0000] "GET /pcapi/records/dropbox/08342hjg9gpqm7g/?_=1363702072225 HTTP/1.1" 200 11139 "-" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (Khtml, like Gecko) Version/4.0 Mobile Safari/533.1"
1.2.3.4 - - [19/Mar/2013:14:08:29 +0000] "GET /pcapi/records/dropbox/08342hjg9gpqm7g/?_=1363702072225 HTTP/1.1" 200 11139 "-" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
更新 - adb logcat
I/Web Console(16747): * at file:///android_asset/www/js/mobile.js:1769
I/Web Console(16747): *** error : : 0 at file:///android_asset/www/js/mobile.js:1779
更新 - TCP/IP 监视器
将请求通过 TCP/IP 监视器显示两个请求都发送了 200 响应。
【问题讨论】:
浏览器日志呢,发生了多少请求? @Gajotres 这不会发生在桌面浏览器中,当在 weire 中运行时,您只会看到一个请求。 您是否可以轻松地模仿我的猜测并增加或减少服务器返回显着长于或短于 30 秒的时间?我很好奇你是否还会看到你得到的 30 秒超时。我问是因为 30 秒是各种事情的相当常见的默认超时值...... @MattGibson 当服务器调用少于 30 秒时,调用只进行一次并返回成功,如果响应大于 30 秒,则重新发送请求并且 ajax 调用返回错误. 您能显示为按钮注册“click”事件处理程序的代码吗?你确定没有在phonegap上注册两次吗? 【参考方案1】:我的应用在 Android 2.3.5 上运行时遇到了这个确切的问题。我只能得出结论,webview 在超时后重试了请求。我找不到影响超时持续时间的方法。
最后,我重写了代码,使初始请求在服务器上分离出一个异步进程并立即返回。然后,从页面上的 setTimer 中,我将检查服务器进程的状态(同样,立即返回)。当状态为“完成”时,页面将进入下一步。
我希望这会有所帮助。我当然理解你对此的不满。我自己花了几天时间与它作斗争。
编辑:这可能是这篇文章让我朝着异步解决方案的方向发展。我相信这里所说的问题是一样的:
XmlHttpRequest double posting issue in Android
【讨论】:
是的,此时,“解决方案”是避免 30 秒的响应时间。在您描述的方法中,或等效方法中,或重新设计服务器端应用程序。【参考方案2】:如果您在此处定义的 URL 路径 url: '/path/to/url'
指向文件夹而不是特定文件,请尝试添加尾部斜杠,如 url: '/path/to/url/'
。
当未指定文件时,Apache Web 服务器会使用新 URL(带有尾部斜杠)向 AJAX 客户端发送 301 重定向,因此客户端会向正确的 URL 发出新请求。
p>请参阅此处发布的类似问题:jQuery $.ajax() executed twice?
在此处查看 Apache 文档参考:http://httpd.apache.org/docs/2.0/mod/mod_dir.html#directoryslash
【讨论】:
URL 是我们的服务器端应用程序,而不是目录。 是的,我知道。我的意思是您的网址是否包含文件名?例如,您的 URL 是www.domain.com/folder/index.php
还是 www.domain.com/folder/
?如果它不包含文件名,请尝试在 URL 后面附加一个斜杠。
您能否发布 Apache 日志中显示这两个请求的条目?
1.2.3.4 - - [19/Mar/2013:14:07:59 +0000] "GET /pcapi/records/dropbox/08342hjg9gpqm7g/?_=1363702072225 HTTP/1.1" 200 11139 " -" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
1.2.3.4 - - [19/Mar/2013:14:08:29 +0000] "GET /pcapi/records/dropbox/08342hjg9gpqm7g/?_=1363702072225 HTTP/1.1" 200 11139 " -" "Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"【参考方案3】:
如何使用beforeSend:
和complete:
AND .ajaxSend()
+ ajaxSuccess()
,也可以试试cache: true
$(document).ajaxSend(function (event, jqxhr, settings)
console.log("triggered ajaxSend !");
if ( submission_active == true )
jqxhr.abort();
submission_active = true;
);
$(document).ajaxSuccess(function (event, xhr, settings)
console.log("triggered ajaxSuccess !");
submission_active = false;
);
$.ajax(
type: "GET",
dataType: "json",
timeout: 30000,
cache: false,
url: '/path/to/url',
success: function(data)
console.debug("**");
,
beforeSend: function(xhr, opts)
if(submission_active == true)
xhr.abort();
submission_active = true;
,
complete: function()
submission_active = false;
error: function(jqXHR, status, error)
console.debug("*** " + status + " : " + error);
);
【讨论】:
如果超时小于响应时间,我会得到一个超时和一个请求。如果超时大于响应时间但小于响应时间 * 2,我会得到一个超时和两个请求。如果超时大于响应时间 * 2,我会收到一个错误和两个请求。 注意:在第三种情况下,错误是在初始请求后正好 60 秒。 不是很相关,但我会检查,在任何情况下,您从 /path/to/url 脚本获得的 JSON 响应都是有效的 JSON,因为空响应不算是有效的,它抛出错误或可能产生不可预知的结果,至少确保您发送并清空(但有效)JSON,如 null 或 (返回json_encode = array();
在 PHP 上就足够了)
如果响应时间少于 30 秒,一切正常。哦,它适用于我测试过的所有其他设备,只有三星 Galaxy S2 会失败
请尝试(希望)改进的答案【参考方案4】:
点击事件被触发两次。下面的代码解决了这个问题。
$('.selector').unbind('click').bind('click', function ()
//...
// Ajax code
//...
);
【讨论】:
事件已触发一次【参考方案5】:我已经在我的移动网站上尝试过这个,唯一的问题是在我的表单中,然后在我的 javascript 上我声明了
$("#button_submit").onclick(function()
//ajax request here
);
如果您使用 ajax,也不要忘记删除表单属性,如操作和方法
希望对你有帮助^_^
【讨论】:
【参考方案6】: <a href="javascript:test()">
那是你的问题。如果您要使用 jquery,请使用他们的 css 选择器!!!!!!!!!那个 href:javascript 的东西在浏览器/设备上都是错误的。
【讨论】:
【参考方案7】:听起来更像是事件传播的问题。我看到了类似的症状(尽管在 ios 上),它归结为 'touchstart' 和 'touchend' 事件都触发了 'click' 事件。你有没有尝试过这样的事情:
$("a").click(function (e)
e.preventDefault();
alert('Clicked');
test();
);
希望这会有所帮助! 干杯 京东
【讨论】:
【参考方案8】:您面临的问题通常称为“弹跳”,它也涉及电子设备中的开关,当您按下并释放按钮时,开关会触发两次,因此您需要为功能设置延迟或取消绑定完成点击后。
您可以使用 Ben Alman 的油门脚本来消除您的点击次数,这对于防止发生多个 ajax 调用非常有用,将其与延迟结合起来,您的问题应该会得到解决
http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
var debounceClick = $.debounce(test, 1000);
function test()
console.debug("*");
$.ajax(
type: "GET",
dataType: "json",
url: '/path/to/url',
success: function(data)
console.debug("**");
,
error: function(jqXHR, status, error)
console.debug("*** " + status + " : " + error + " : " + jqXHR.status);
,
cache: false
);
现在调用链接中的 debounceClick 函数来解决您的问题。
或者,您也可以使用没有油门插件的简单纯 javascript 来实现您的结果:
var timeout;
function test()
console.debug("*");
$.ajax(
type: "GET",
dataType: "json",
url: '/path/to/url',
success: function(data)
console.debug("**");
,
error: function(jqXHR, status, error)
console.debug("*** " + status + " : " + error + " : " + jqXHR.status);
,
cache: false
);
function click()
if(timeout)
clearTimeout(timeout);
timeout = setTimeout(test, 1000);
在本例中,将 click() 函数绑定到您的链接。
【讨论】:
但该事件只触发一次【参考方案9】:我遇到了同样的问题,我在提交按钮上绑定了点击事件,ajax 运行了两次。
我没有绑定事件,而是在按钮上使用了onClick
方法,如下所示
<button onclick"myProcess()"></button>
它解决了我的问题。
【讨论】:
以上是关于jquery ajax GET请求执行两次的主要内容,如果未能解决你的问题,请参考以下文章
jQuery.get(url, [data], [callback], [type])