JavaScript数组管理之谜

时间:2011-07-28 22:29:27

标签: javascript ajax arrays jquery

支持一个令人困惑的解释。我正在制作一个愚蠢的小测验网站。页面上有五个问题。存储在xml文件中的答案。问题会随时向玩家显示,并提供输入以供他们回答。当玩家猜测某个特定答案时,JQuery会将猜测发布到一个php文件,该文件根据xml中存储的内容检查答案,并返回1(正确)和/或0(错误)。帖子由文本输入的keyup事件触发。

我有一个名为剩余的全局数组,用于存储仍待回答的页面上的问题。这是在页面加载时使用值[1,2,3,4,5]填充的。正确回答问题后,将删除相应的数字。因此,如果玩家回答问题1,剩余将包含[2,3,4,5]。

var current;
var remaining;

$(document).ready(function() {

    // What question the player is on.
    current = 1; 

    // Questions unanswered.
    remaining = new Array(1, 2, 3, 4, 5);

    $('#in').keyup(function() {
        // Send answer to server to check if it's right.
        CheckGuess($(this).val());  
    });

});

function CheckGuess(guess) {

if (guess.length > 2 && guess.length < 100) 
{
    $.post( 
        "class/check.php",
        "current=" + current + "&answer=" + guess,
        function(check) {

             if (check == 1) {
                    AnswerCorrect();
             }

        },
        "json"
    );
}   
}

function AnswerCorrect() {

// User guessed correctly.

if (remaining.length != 1) {

    var next;

    // Remove complete question from array of remaining values.
    for (var i = 0; i < remaining.length; i++ ) {
        if (remaining[i] == current) {          

            // Set the next question. It will be the next one in the array 
            // or the previous if the current question is the last in the array.
            if (i != (remaining.length - 1)) {
                next = remaining[i + 1];
            } else {
                next = remaining[i - 1];
            }

            debugger;

            // Remove current question.
            remaining.splice(i, 1);

            // Get out of the for loop.
            break;

        }           
    }   

    // Set current as next.
    current = next;

    // Set the href for the next question.
    var destination = "#m" + next;

    // Scroll to next question.
    $.scrollTo($(destination), { duration: 1000});

    // Clear input box.
    $("#in").val("");

}

else {
    // Quiz complete.
}

}

这一切都在某种程度上起作用。但是我遇到了一些神秘的问题。我已经使用FireBug逐步完成了它,似乎发生了什么:

  • (a)中。页面加载。我可以看到剩余的具有我想要的值[1,2,3,4,5]。
  • (b)中。玩家输入问题1的正确答案。然后从剩余中删除“1”,使其具有预期的值[2,3,4,5]。
  • (c)中。玩家输入问题2的正确答案,但现在一旦FireBug遇到我设置的任何断点,我就可以看到剩余的具有值[3,4,5]。所以在调用函数 AnswerCorrect()之前,2已经消失了。 2去哪儿了?!然后当 AnswerCorrect()确实运行时,它认为播放器在问题3上(因为剩余包含[3,4,5])。总体结果是当玩家回答问题2时,2和3都被标记为正确。

我希望我的解释有点清楚。在我的生活中,我从未理解过任何东西。我不明白上面的(b)和(c)点之间发生了什么。我正在逐步完成代码,但我无法找到剩余丢弃“2”的位置。 FireBug让我失望。它应该在某个地方似乎没有破坏。如果我在 split()上有断点,我看不到2的删除可能会在没有我看到的情况下继续。有人有任何线索吗?在我发疯之前,我真的很感激你的帮助。

编辑 - 更多信息

(对不起,答复很慢,我整天都在上班。)

真正的问题是我无法看到 2 被删除的位置。我想到的一件事可能就是问题(但是我不太了解Javascript是否有可能):

jQuery帖子经常发布;每次玩家输入一封信。是否有可能同时多次调用 AnswerCorrect()?那么 AnswerCorrect()的两个或多个“实例”同时运行?

编辑2

我决定放弃这种方法。我无法弄清楚这个问题。我重写了它,以便现在帖子发生在文档加载上,答案存储在服务器端的数组中。无论如何,这可能是一种更好的方式,因为我只有一个帖子到服务器而不是很多。现在一切正常。考虑这个线程已解决。

2 个答案:

答案 0 :(得分:0)

我认为你的事情过于复杂。不需要循环或拼接,并且在循环中,您将数组索引与数组值混合以试图找出您的位置。这非常令人困惑 - 即使你已经弄明白了,下一个出现并保持下去的人也会丢失(即使那是你从现在开始的6个月)。

您希望第一个项目离开数组,并且您希望相应地修改数组长度。为此,您应该使用Array.prototype.shift()。我已经重新安排了一些代码以获得更好的实践,但是试图将其中一些代码保留在相同的布局中,以避免让它无法识别:

var remaining = [ 1, 2, 3, 4, 5 ];

$( function()
{
    $( '#in' ).keyup( function()
    {
        // Send answer to server to check if it's right.
        CheckGuess( $( this ).val() );  
    } );

    Next();
} );

function CheckGuess( guess )
{
    if( guess.length > 2 && guess.length < 100 )
    {
        $.post( 
            'class/check.php',
            {
                current: + current,
                answer + guess
            },
            function( check )
            {
                if( check == 1 )
                {
                    Next();
                }
            },
            'json'
        );
    }   
}

function Next()
{
    // User guessed correctly.
    if( remaining.length )
    {
        current = remaining.shift();

        // Scroll to next question.
        $.scrollTo( $( '#m' + current ), { duration: 1000 } );

        // Clear input box.
        $( '#in' ).val( '' );
    }
    else
    {
        // Quiz complete.
    }
}

答案 1 :(得分:0)

我老实说,您发布的代码中没有任何逻辑错误。我将它放在jsFiddle here中,模拟异步检查是正确的,每次都查看剩余的答案。它似乎对我有用。所以,如果您的真实代码是您正在讨论的问题,那么代码中必须有其他内容,您没有在此处向我们展示过。

在具有异步ajax调用的应用程序中,事情可能出错的一个典型位置是这样,并且某些全局状态是异步部分可能无法正确完成。在更改任何状态之前,必须等待服务器调用的成功处理程序。如果在处理之前状态发生了变化,那么当它完成时它可能会搞砸。

如果您可以假设数组中的第一个问题始终是正在处理的问题,那么其他两个答案建议的是更简单的编写代码的方法。您的AnswerCorrect()代码并不假设唯一正在处理的答案是数组中的第一个,因此更通用,所以如果是这种情况,那么我认为您不能使用其他代码答案。

所以,我认为你的问题的答案是,导致错误的原因必须多于你在问题中披露的内容,因为我没有看到你发布的内容和“模拟”的任何严重的逻辑错误“jsFiddle使用你的代码似乎工作。那么,你的应用中还有什么东西没有在这里展示给我们?

修改

首次使用ajax调用时最常见的错误与ajax调用的异步性质有关。当你进行调用时,它会启动ajax调用,它会在后台发生,而其余的代码会继续运行。直到调用完成/成功函数之后的某个时间才完成。如果你忘记了这个事实,并且在你完成之前启动ajax调用后你做了其他事情,那么你的逻辑就会出错。你在这里发布的样本没有那个问题,但是我猜想在POST到服务器后你的实际代码还有更多,也许这就是错误/混淆的根源。由于您使用一些全局变量来跟踪状态,如果在POST调用之后和调用完成函数之前触摸任何这些全局变量(比如转到下一个问题),它将搞乱你的逻辑。成功功能将通过,您的全局状态将被错误地更改。这只是一个猜测,因为我必须经历的是您发布的代码,它没有您遇到的问题。

如果你想发布真实的代码或给我们一个真实页面的链接,我们可以看看那里。