为什么我的AJAX功能调用回调多次?我的、回调、功能、AJAX

2023-09-10 16:42:40 作者:冷眸冰泪

我做了一个ajax功能后,当我一旦称呼它,传递给它结束了回调函数获取调用3次。 为什么回调被调用多次?

I've made an ajax post function, and when I call it once, the callback function that is passed to it ends up getting called 3 times. Why is the callback being called multiple times?

我试图用javascript模式,使用封闭包装一样的功能在一个全局变量模块。我的AJAX组件是它自己的文件,如下所示:

I'm attempting to use a "module" javascript pattern that uses closures to wrap like functionality under one global variable. My ajax module is its own file, and looks like this:

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));

主要应用也是它自己的文件。它作为一个例子,看起来是这样的:

The main application is also it's own file. It, as an example, looks like this:

// 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次。

As you can see, I'm trying to bring in dependencies as local variables/namespaces. When this runs, it pops up the alert box 3 times.

我不知道如果这个问题是由于AJAX功能本身或整体结构(或两者),所以我倒是在任美联社preciate的意见和想法。

I'm not sure if this problem is due to the ajax function itself or the overall architecture (or both), so I'd appreciate comments or thoughts on either.

我已经试过未包装的匿名函数的程序的主要部分,但是这并没有帮助。提前致谢!

I've tried un-wrapping the main part of the program from the anonymous function, but that didn't help. Thanks in advance!

修改 下面是完整的HTML文件,所以你可以看到为了我包括<脚本> 的在

Here's the entire HTML file, so you can see the order I include the <script>'s in.

<!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:的

EDIT 2:

我在我的例子一个错字,并改变

I had a typo in my example, and changed

(function (window, document, bigmap, ajax) {

(function (window, document, ajax) {

修改3:的

EDIT 3:

我已经改变了的onreadystatechange 功能登录就绪状态到控制台:

I've changed the onreadystatechange function to log the ready state to the console:

XHR.onreadystatechange = function () {
    console.log("readyState: " + XHR.readyState);
    if (XHR.readyState === done && XHR.status === ok) {
        callback(XHR.responseText);
    }
};

当我通过code。在谷歌浏览器的步骤,回调被称为三次,控制台日志:

When I step through the code in Google Chrome, the callback is called three times, and the console logs:

readyState: 4
readyState: 4
readyState: 4

然而,当我运行该页面为正常现象,不通过它一步,功能运行正常,仅运行回调一次。在这种情况下,控制台日志:

However, when I run the page as normal and don't step through it, the function works as expected and only runs the callback once. In this case, the console logs:

readyState: 2
readyState: 3
readyState: 3
readyState: 4

所以,现在我的问题是,为什么通过code步进回调时多次调用?

解决的:

当我问到这个问题,我没有意识到的它只是发生在调试时,我是加强过code 的。

When I asked this question, I didn't realize that it was only happening when I was stepping through the code while debugging.

于是,国家改变了3次,但执行已经被推迟了破发点,让所有3 的onreadystatechange 功能查看当前的4个国家,而不是什么国家的是的变化确实时有发生。

So, the state changed 3 times, but execution has been delayed by the break-point, so all 3 onreadystatechange functions see the current state of 4, instead of what the state was when the change actually occurred.

外卖是,的onreadystatechange 更改不会存储什么状态。相反,它会读取的readyState 的的时候它的执行,即使程序被中断,并且状态再次改变的平均时间的

The takeaway is that onreadystatechange change does not store what that state is. Instead, it reads the readyState at the time its executed, even if the program gets interrupted, and the state changes again in the mean time.

因此​​,AJAX需要不同的调试技术比你有完全同步的code使用......但你可能已经知道了。

Therefore, AJAX requires different debugging techniques than you use with completely synchronous code... but you probably already knew that.

感谢大家谁帮助在这里。

推荐答案

的readyState 有4个截然不同的状态:

The readyState has 4 distinct states:

0 - 无请求初始化 1 - 连接到服务器 2 - 请求被接受 3 - 加工 4 - 完成,收到响应

0 - no request initialized 1 - connected to server 2 - request was received 3 - processing 4 - Done, response received

每个这些变化将调用的onreadystatechange 处理程序。这就是为什么大多数的这些功能​​将是这样的:

Each of these changes will call the onreadystatechange handler. That's why most of these functions will look like this:

xhr.onreadystatechange = function()
{
    if (this.readyState === 4 && this.status === 200)
    {
        //do stuff with this.responseText
    }
}

只是硬code当中,而不是使用不可靠的变量(名称完成确定似乎危险的我)。

Just hard-code them, instead of using dodgy variables (the names done and ok seem dangerous to me).

除此之外,尝试宣告函数直接返回的对象:

Other than that, try declaring the post function either directly in the returned object:

return {post : function()
{
};

或者作为一个匿名。函数,赋值给变量

var post = function(){};

各种发动机做各种事情与功能,你声明它们的方式,提升他们的,换一个。此外感觉不对的函数名,如果你问我...我会尝试使用名称不像他们的可能的保留...

Various engines do various things with functions, the way you declare them, hoisting them, for one. Also post doesn't feel right as a function name if you ask me... I'd try to use names that don't look like they might be reserved...

此外,你没有明确设置XHR的 X-要求 - 以标题:

Also, you're not explicitly setting the XHR's X-Requested-With header:

XHR.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

这可能只是什么导致了问题(HTTP1.1和传输编码分块?)

Which might just be what's causing the problem (HTTP1.1 and transfer-encoding chunked?)

为使调试容易,尝试每次警报通过改变回调(XHR.responseText)显示了记录XHR对象; 回调。申请(这一点,[this.responseText]); ,尽管这些说法是多余的。然后,将 ajax.post(PHP / paths.php,空,函数(){window.alert(1);}); 来:

To make debugging easier, try logging the XHR object each time the alert shows up by changing callback(XHR.responseText); to callback.apply(this,[this.responseText]);, although the argument is redundant. Then, change ajax.post("php/paths.php", null, function () { window.alert("1"); }); to:

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
});