我已经创建了一个ajax post函数,当我调用它一次时,传递给它的回调函数最终被调用3次。 为什么多次调用回调?
我正在尝试使用“模块”javascript模式,该模式使用闭包在一个全局变量下包含类似功能。我的ajax模块是它自己的文件,看起来像这样:
var ajax = (function (XMLHttpRequest) {
"use strict";
var done = 4, ok = 200;
function post(url, parameters, callback) {
var XHR = new XMLHttpRequest();
if (parameters === false || parameters === null || parameters === undefined) {
parameters = "";
}
XHR.open("post", url, true);
XHR.setRequestHeader("content-type", "application/x-www-form-urlencoded");
XHR.onreadystatechange = function () {
if (XHR.readyState === done && XHR.status === ok) {
callback(XHR.responseText);
}
};
XHR.send(parameters);
}
// Return the function/variable names available outside of the module.
// Right now, all I have is the ajax post function.
return {
post: post
};
}(parent.XMLHttpRequest));
主应用程序也是它自己的文件。作为一个例子,它看起来像这样:
// Start point for program execution.
(function (window, document, ajax) {
"use strict";
ajax.post("php/paths.php", null, function () { window.alert("1"); });
}(this, this.document, parent.ajax));
正如您所看到的,我正在尝试将依赖项作为局部变量/命名空间引入。当它运行时,它会弹出警报框3次。
我不确定这个问题是由于ajax函数本身还是整体架构(或两者),所以我很欣赏它们的评论或想法。
我尝试从匿名函数中解压缩程序的主要部分,但这没有帮助。提前致谢!
修改 的
这是整个HTML文件,因此您可以看到我包含<script>
的订单。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="expires" conent="0" />
<title>Mapalicious</title>
<link href="css/main.css" type="text/css" rel="stylesheet" />
<script src="js/raphael.js"></script>
</head>
<body>
<div id="map"></div>
<script src="js/promise.js"></script>
<script src="js/bigmap.js"></script>
<script src="js/ajax.js"></script>
<script src="js/init.js"></script>
</body>
</html>
编辑2:
我的示例中有一个拼写错误,并且已更改
(function (window, document, bigmap, ajax) {
到
(function (window, document, ajax) {
编辑3:
我已将onreadystatechange
函数更改为将就绪状态记录到控制台:
XHR.onreadystatechange = function () {
console.log("readyState: " + XHR.readyState);
if (XHR.readyState === done && XHR.status === ok) {
callback(XHR.responseText);
}
};
当我浏览谷歌浏览器中的代码时,回调被调用三次,控制台记录:
readyState: 4
readyState: 4
readyState: 4
但是,当我正常运行页面并且不单步执行时,该函数按预期工作,只运行一次回调。在这种情况下,控制台记录:
readyState: 2
readyState: 3
readyState: 3
readyState: 4
所以现在我的问题是,为什么在单步执行代码时多次调用回调?
解决:
当我问这个问题时,我没有意识到只有当我在调试时单步调试代码时才会发生这种情况。
所以,状态改变了3次,但执行时间被延迟了,因此所有3个onreadystatechange
函数都看到当前状态为4,而不是状态实际发生变更时, 。
外卖是onreadystatechange
更改不存储该状态。相反,它会在执行时读取readyState
,即使程序被中断,状态也会在同一时间再次发生变化。
因此,AJAX需要不同于完全同步代码的调试技术......但你可能已经知道了。
感谢所有在此提供帮助的人。
答案 0 :(得分:9)
readyState
有4种不同的状态:
0 - 没有请求初始化
1 - 连接到服务器
2 - 收到请求
3 - 处理
4 - 完成,收到回复
这些更改中的每一个都将调用onreadystatechange
处理程序。这就是为什么大多数这些功能看起来像这样:
xhr.onreadystatechange = function()
{
if (this.readyState === 4 && this.status === 200)
{
//do stuff with this.responseText
}
}
只是对它们进行硬编码,而不是使用狡猾的变量(名称done
和ok
对我来说似乎很危险)。
除此之外,尝试直接在返回的对象中声明post
函数:
return {post : function()
{
};
或者作为一个匿名者。函数,分配给变量post
:
var post = function(){};
各种引擎通过功能,你声明它们的方式,提升它们来做各种事情。如果你问我,post
作为一个函数名称感觉不对...我会尝试使用看起来不像可能保留的名字... < / p>
此外,您没有明确设置XHR的X-Requested-With
标题:
XHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
这可能只是导致问题的原因(HTTP1.1和转码编码分块?)
为了使调试更容易,请尝试通过将callback(XHR.responseText);
更改为callback.apply(this,[this.responseText]);
来每次显示警报时记录XHR对象,尽管参数是多余的。然后,将ajax.post("php/paths.php", null, function () { window.alert("1"); });
更改为:
ajax.post("php/paths.php", null,
function (response)
{
console.log(this.readyState);//or alert the readyState
window.alert(response);//check the response itself, for undefined/valid responses
});
答案 1 :(得分:0)
在我看来,你的ajax对象正在返回对post函数的调用。如果是这样,并且你正在调用ajax变量上的post函数,那么它不会至少调用post两次:一次是对象的实例化,另一次是方法调用吗?
答案 2 :(得分:0)
我在使用ajax方面相当新,但我遇到的问题与我要解决的问题相同。我一直在读w3学校的ajax。我注意到,当状态被选中时,他们使用this.readystate
和this.status
而不是 object.readystate
。我认为由于某种原因,它会在object.readystat
e上触发三次并且与this.readystate
一起正常工作。我明天会检查,但我认为这可能是问题。