找不到错误 - 发射次数太多

Can't find the bug - too many firings

本文关键字:太多 发射 错误 找不到      更新时间:2023-09-26

(编辑了一些拼写错误(

因此,这里有一段代码,它会在用户对 MPC 问题给出的每个答案中重复自己:

  • 它触发问题,生成 4 个答案,将"单击"和"鼠标悬停"绑定到答案,并等待用户实际单击其中一个。
  • 当他这样做时,它会检查它是对还是错,向用户显示,然后等待另一个输入(这次是文档中的任何位置(,然后再继续并重复。

现在,这个想法是用户可以用光标单击,或使用 QWER 来回答。由于我对事件及其数据的操纵很陌生,我找到了一种(显然有缺陷的(将两者分开的方法,如下所示。

但是,当用户通过单击"回答",

并通过QWER"继续"时,它会通过实际按预期触发问题,然后立即回答并再次触发另一个问题来快速完成整个事情。(在将此操作所需的时间提取到数组中后,我发现它有时会连续执行此操作 3-6 次,根本没有明显的原因

......

现在,如前所述,当涉及到事件时,我是新手,所以可能会有冗余和/或错误使用(e(,但请耐心等待。当然,我希望该错误与此有关。此外,有些函数在这里是无关紧要的,因为它们会回到它们的调用所在的任何函数(right((;例如,在自身之后不会触发任何内容(。

循环

才是这里的重点。

提前感谢!

代码如下:

function keyAns() {
    answered="no";
    draw(0);
}
function keyNotAns (A) {
    B = $(A).children('.answer');
    if ($(B).hasClass('right')) {
        // do something
    }
    else if ($(B).hasClass('wrong')) {
        // do something
    }
    answered = "yes";
}
function waitForInput() {
    // MOUSE CLICK
    $(document).click(function() {
        if (answered == "yes") {
            answered = "no";
            draw(0);
        }
    });
    $('.answer').click(function(e) {
        $('.answer').unbind('click');
        if (answered == "no") {
            calcTime(1);
            e.stopPropagation();
            if ($(this).hasClass('right')) {
                // do something
            }
            else if ($(this).hasClass('wrong')) {
                // do something
            }
            answered = "yes";
        }
    });
    // KEYPRESSES
    $(document).bind('keyup', function(e){
        $(document).unbind('keyup');
        if (answered == "yes") {
            e.stopPropagation();
            keyAns();
        }
        else if ( answered == "no") {
            calcTime(1);    // irrelevant
            if(e.which == 81 || e.keyCode == 81) { // Q
                AAA = '#ansQ';
                e.stopPropagation();
                keyNotAns(AAA);
            }
            else if(e.which == 87 || e.keyCode == 87) { // W
                AAA = '#ansW';
                e.stopPropagation();
                keyNotAns(AAA);
            }
            else if(e.which == 69 || e.keyCode == 69) { // E
                AAA = '#ansE';
                e.stopPropagation();
                keyNotAns(AAA);
            }
            else if(e.which == 82 || e.keyCode == 82) { // R
                AAA = '#ansR';
                e.stopPropagation();
                keyNotAns(AAA);
            }
            else {
            }
            waitForInput();
        }
    });
}

每次有按键事件时,您都会重新绑定所有内容。

这意味着,如果您按 10 个键,您将拥有 10 个onclick侦听器。因此,当用户单击时,回调将连续运行 10 次。

您发布的代码不包括对 waitForInput 函数的原始调用,但您只需要调用它一次,因此您可以从此代码中删除它。

jquery 事件的快速介绍:

当您bind 时,每次发生该事件(在您将其放入的元素上(时,您提供的回调函数都将运行。

另一个提示是,在较新版本的jQuery中,有一个名为one的绑定的替代方法。它执行相同的操作,但只会运行第一次。虽然在这种情况下,你不需要它。

你的问题是在你的键绑定中,你正在调用waitForInput .

异步编程需要一些时间来适应,但是 waitForInput 中的函数所做的是设置事件侦听器,每当事件发生时,这些侦听器都会触发。

看到的问题是,在处理事件后,您正在添加更多事件侦听器,下次触发事件时,侦听器将触发多次。

只需从函数中删除waitForInput()行,并将其放在代码的底部即可。 然后它只会运行一次,你会没事的。 (将其重命名为类似 setupEventListeners 的东西不会有什么坏处,以避免混淆。

找到了!

这一切都要感谢Scott MermelsteinColBeseder,他们对我的解决方案同样宝贵!他们不仅发现了缺陷,还让我了解了事件绑定的工作原理。所以谢谢一百万,你们两个!

事实上:

  • 绑定正在堆叠,因此如果它触发,它也会过度触发;
  • 然而,waitForinput(( 的自调用确实是不需要的;
  • 还需要一个 e.stopPropagation((,以防止循环处理错误的事件数据,这导致函数将其解释为下一个答案并再次触发自己。

另外:由于懒惰 - 我不觉得太多的试验和错误 - 我想保持安全,所以我在函数触发时添加了所有unbind((作为第一件事。

对于那些感兴趣的人,结果完美无缺

function keyNotAns (A) {
    B = $(A).children('.answer');
    if ($(B).hasClass('right')) {
        // do something
    }
    else if ($(B).hasClass('wrong')) {
        // do something
    }
    answered = "yes";
}
function waitForInput() {
    $(document).unbind('keyup');
    $(document).unbind('click');
    $('.answer').unbind('click');
    // MOUSE CLICKS
    $(document).click(function() {
        if (answered == "yes") {
            answered = "no";
            draw(0);
        }
    });
    $('.answer').click(function(e) {
        if (answered == "no") {
            calcTime(1);
            if ($(this).hasClass('right')) {
                // do something
            }
            else if ($(this).hasClass('wrong')) {
                // do something
            }
            e.stopPropagation();
            answered = "yes";
        }
    });
    // KEYPRESSES
    $(document).bind('keyup', function(e){
        if (answered == "yes") {
            answered="no";
            draw(0);
        }
        else if (answered == "no") {
            if(e.which == 81 || e.keyCode == 81) { // Q
                keyNotAns('#ansQ');
            }
            else if(e.which == 87 || e.keyCode == 87) { // W
                keyNotAns('#ansW');
            }
            else if(e.which == 69 || e.keyCode == 69) { // E
                keyNotAns('#ansE');
            }
            else if(e.which == 82 || e.keyCode == 82) { // R
                keyNotAns('#ansR');
            }
        }
    });
}

有两种方法可以找到此类错误。第一个是使用调试器 - 当你有循环时,这可能非常乏味。

第二种方法是日志记录:编写所有重要操作的报告/日志,以便稍后阅读,以找出它在过去某个时候失败的原因。

看看console.log()或JavaScript日志记录框架。